Canvas.c 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874
  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. /* $TOG: Canvas.c /main/40 1999/10/14 13:17:22 mgreess $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: Canvas.c
  28. **
  29. ** Project: Cde Help System
  30. **
  31. ** Description: UI independent layer for the help system. These
  32. ** routines manage the information within a 'canvas'.
  33. ** The 'canvas' routines call UI dependent code to
  34. ** render the information.
  35. **
  36. ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
  37. **
  38. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  39. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  40. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  41. ** (c) Copyright 1993, 1994 Novell, Inc.
  42. ****************************************************************************
  43. ************************************<+>*************************************/
  44. /*
  45. * system includes
  46. */
  47. #include <stdlib.h>
  48. #include <string.h>
  49. /*
  50. * Canvas Engine includes
  51. */
  52. #include "CanvasP.h"
  53. #include "CanvasSegP.h"
  54. /*
  55. * private includes
  56. */
  57. #include "CanvasI.h"
  58. #include "CvStringI.h"
  59. #include "LinkMgrI.h"
  60. #include "LayoutUtilI.h"
  61. #include "SelectionI.h"
  62. #include "VirtFuncsI.h"
  63. #ifdef NLS16
  64. #endif
  65. /******** Private Function Declarations ********/
  66. static _DtCvUnit DrawText(
  67. _DtCanvasStruct *canvas,
  68. _DtCvDspLine *line,
  69. int txt_line,
  70. _DtCvFlags old_flag,
  71. _DtCvFlags new_flag );
  72. /******** End Private Function Declarations ********/
  73. /*****************************************************************************
  74. * Private Variables
  75. *****************************************************************************/
  76. static _DtCanvasStruct DefaultCanvas =
  77. {
  78. 0, /* int error; */
  79. 0, /* int txt_cnt; */
  80. 0, /* int txt_max; */
  81. 0, /* int line_cnt; */
  82. 0, /* int line_max; */
  83. 0, /* int mark_cnt; */
  84. 0, /* int mark_max; */
  85. 0, /* int trav_cnt; */
  86. 0, /* int trav_max; */
  87. 0, /* int cur_trav; */
  88. 0, /* search_cnt */
  89. 0, /* search_max */
  90. 0, /* brk_cnt */
  91. 0, /* brk_max */
  92. 1, /* short mb_length; */
  93. 0, /* _DtCvUnit max_x; */
  94. 0, /* _DtCvUnit max_y; */
  95. _DtCvIGNORE_BOUNDARY, /* _DtCvValue constraint; */
  96. _DtCvFALSE, /* _DtCvValue trav_on; */
  97. NULL, /* _DtCvPointer client_data; */
  98. { /* CanvasMetrics metrics; */
  99. 0, /* _DtCvUnit width; */
  100. 0, /* _DtCvUnit height; */
  101. 0, /* _DtCvUnit top_margin; */
  102. 0, /* _DtCvUnit line_height; */
  103. 0, /* _DtCvUnit horiz_pad_hint; */
  104. },
  105. { /* _DtCvSpaceMetrics link_info; */
  106. 0, /* _DtCvUnit space_before; */
  107. 0, /* _DtCvUnit space_after; */
  108. 0, /* _DtCvUnit space_above; */
  109. 0, /* _DtCvUnit space_below; */
  110. },
  111. { /* _DtCvSpaceMetrics traversal_info; */
  112. 0, /* _DtCvUnit space_before; */
  113. 0, /* _DtCvUnit space_after; */
  114. 0, /* _DtCvUnit space_above; */
  115. 0, /* _DtCvUnit space_below; */
  116. },
  117. { /* _DtCvLocale locale; */
  118. _DtCvModeWrapNone, /* _DtCvModeType line_wrap_mode; */
  119. NULL, /* const wchar_t *cant_begin_chars; */
  120. NULL, /* const wchar_t *cant_end_chars; */
  121. },
  122. NULL, /* _DtCvSegment *element_lst; */
  123. NULL, /* _DtCvDspLine *txt_lst; */
  124. NULL, /* _DtCvLineSeg *line_lst; */
  125. NULL, /* _DtCvTraversalInfo *trav_lst; */
  126. NULL, /* _DtCvLinkDb link_data; */
  127. { /* CESelection select_start; */
  128. -1, /* _DtCvUnit x; */
  129. -1, /* _DtCvUnit y; */
  130. -1, /* int line_idx; */
  131. -1, /* int char_idx; */
  132. },
  133. { /* CESelection select_end; */
  134. -1, /* _DtCvUnit x; */
  135. -1, /* _DtCvUnit y; */
  136. -1, /* int line_idx; */
  137. -1, /* int char_idx; */
  138. },
  139. NULL, /* _DtCvMarkData *marks; */
  140. NULL, /* searchs */
  141. NULL, /* pg_breaks */
  142. { NULL }, /* _DtCvVirtualInfo virt_functions; */
  143. };
  144. /*****************************************************************************
  145. * Private Functions
  146. *****************************************************************************/
  147. /*****************************************************************************
  148. * Function: RenderSubSet
  149. *
  150. * Returns: nothing
  151. * Purpose: Render the items next to an item of text.
  152. *
  153. *****************************************************************************/
  154. static void
  155. RenderSubSet (
  156. _DtCanvasStruct *canvas,
  157. _DtCvDspLine *lines,
  158. int cnt,
  159. _DtCvUnit y1,
  160. _DtCvUnit y2,
  161. _DtCvUnit *last_y)
  162. {
  163. int i;
  164. _DtCvUnit minY;
  165. _DtCvUnit maxY;
  166. /*
  167. * Loop through the list looking for the item(s) next to the text.
  168. */
  169. for (i = 0; NULL != lines && i < cnt; lines++, i++)
  170. {
  171. /*
  172. * get the minimum and maximum y of the next line
  173. */
  174. minY = lines->baseline - lines->ascent;
  175. maxY = lines->baseline + lines->descent;
  176. /*
  177. * has this line been reviewed yet?
  178. * is this line on the 'page'?
  179. * Does it hang off the 'page' (and if so is it allowed)?
  180. */
  181. if (_DtCvIsNotProcessed(*lines) && maxY >= y1 && maxY <= y2)
  182. {
  183. (void) DrawText (canvas, lines, i, 0, 0);
  184. /*
  185. * indicate that this line has been rendered.
  186. */
  187. _DtCvSetProcessed(*lines);
  188. /*
  189. * is this the maximum that we've rendered?
  190. */
  191. if (*last_y < maxY)
  192. *last_y = maxY;
  193. /*
  194. * now render anything next to this!
  195. */
  196. RenderSubSet(canvas, canvas->txt_lst, cnt, minY, y2, last_y);
  197. }
  198. }
  199. }
  200. /*****************************************************************************
  201. * Function: CheckAround
  202. *
  203. * Returns: _DtCvSTATUS_NONE if no other text is to the side of
  204. * this text.
  205. * _DtCvFALSE if other text is to the side, but the
  206. * maximum y position is not violated.
  207. * _DtCvTRUE if other text is to the side and the
  208. * maximum y position is violated.
  209. * Purpose: Find if another line of text intrudes upon this line.
  210. *
  211. *****************************************************************************/
  212. static _DtCvStatus
  213. CheckAround (
  214. _DtCvDspLine *lines,
  215. int cnt,
  216. int idx,
  217. _DtCvUnit y2)
  218. {
  219. int i = 0;
  220. _DtCvUnit topY = lines[idx].baseline - lines[idx].ascent;
  221. _DtCvUnit botY = lines[idx].baseline + lines[idx].descent;
  222. _DtCvUnit minY;
  223. _DtCvUnit maxY;
  224. _DtCvStatus result = _DtCvSTATUS_NONE;
  225. /*
  226. * set the processed flag so that we don't test something that's
  227. * already tested.
  228. */
  229. _DtCvSetProcessed(lines[idx]);
  230. /*
  231. * go through looking for unprocessed lines to test.
  232. */
  233. while (i < cnt && _DtCvTRUE != result)
  234. {
  235. if (_DtCvIsNotProcessed(lines[i]))
  236. {
  237. /*
  238. * calculate the minimum and maximum y positions for the line.
  239. */
  240. minY = lines[i].baseline - lines[i].ascent;
  241. maxY = lines[i].baseline + lines[i].descent;
  242. /*
  243. * Does this line infringe vertically on the test line?
  244. */
  245. if (maxY > topY && minY < botY &&
  246. _DtCvTRUE == _DtCvCheckInfringement(topY, botY, minY, maxY))
  247. {
  248. /*
  249. * indicate that it is not clear to the side.
  250. */
  251. result = _DtCvFALSE;
  252. /*
  253. * Does it have something else infringing one it?
  254. * Or does it hang down below the test line?
  255. */
  256. if (maxY > y2 || _DtCvTRUE == CheckAround(lines, cnt, i, y2))
  257. result = _DtCvTRUE;
  258. }
  259. }
  260. i++;
  261. }
  262. /*
  263. * Clear that this line has be processed. Otherwise, rendering will
  264. * think this has been rendered when it hasn't.
  265. */
  266. _DtCvClearProcessed(lines[idx]);
  267. return result;
  268. }
  269. /*****************************************************************************
  270. * Function: FindChar
  271. *
  272. * FindChar calculates the char that is x pixels into the string.
  273. *
  274. *****************************************************************************/
  275. static int
  276. FindChar (
  277. _DtCanvasStruct *canvas,
  278. _DtCvSegmentI *segment,
  279. void *string,
  280. int max_len,
  281. _DtCvUnit x_pos,
  282. _DtCvUnit *diff)
  283. {
  284. int myIndex;
  285. _DtCvUnit myDiff = 0;
  286. _DtCvUnit len;
  287. _DtCvUnit charWidth;
  288. _DtCvValue triedBack = False;
  289. _DtCvValue triedForward = False;
  290. /*
  291. * get information about the font used
  292. */
  293. _DtCvFontMetrics(canvas, _DtCvFontOfStringSeg(segment),
  294. NULL, NULL, &charWidth, NULL, NULL);
  295. /*
  296. * try to get close to the correct index.
  297. */
  298. myIndex = x_pos / charWidth;
  299. if (myIndex >= max_len)
  300. myIndex = max_len - 1;
  301. while (!triedBack || !triedForward)
  302. {
  303. len = _DtCvGetStringWidth(canvas, segment, string, myIndex + 1);
  304. if (len > x_pos)
  305. {
  306. myDiff = len - x_pos;
  307. triedForward = True;
  308. if (!triedBack && myIndex)
  309. myIndex--;
  310. else
  311. triedBack = True;
  312. }
  313. else if (len < x_pos)
  314. {
  315. myDiff = x_pos - len;
  316. triedBack = True;
  317. myIndex++;
  318. if (myIndex >= max_len)
  319. {
  320. myIndex--;
  321. triedForward = True;
  322. }
  323. }
  324. else /* len == x_pos */
  325. {
  326. myIndex++;
  327. triedBack = True;
  328. triedForward = True;
  329. myDiff = 0;
  330. }
  331. }
  332. if (diff != NULL)
  333. *diff = myDiff;
  334. return (myIndex);
  335. }
  336. /*****************************************************************************
  337. * Function: DrawCanvasLines
  338. *
  339. *****************************************************************************/
  340. static void
  341. DrawCanvasLines(
  342. _DtCanvasStruct *canvas,
  343. _DtCvUnit x1,
  344. _DtCvUnit y1,
  345. _DtCvUnit x2,
  346. _DtCvUnit y2,
  347. _DtCvRenderType flag,
  348. _DtCvUnit *ret_y,
  349. _DtCvUnit *ret_next)
  350. {
  351. int i;
  352. _DtCvUnit newY2 = y2;
  353. _DtCvLineSeg *pLS;
  354. _DtCvLineInfo lnInfo;
  355. /*
  356. * are there any lines?
  357. */
  358. if (canvas->line_lst != NULL && canvas->line_cnt &&
  359. NULL != canvas->virt_functions.render_elem)
  360. {
  361. /*
  362. * find the maximum y of all the lines that fit in the page.
  363. * do this only if the flag indicates whole lines.
  364. */
  365. if (_DtCvRENDER_COMPLETE == flag)
  366. {
  367. for (i = 0, pLS = canvas->line_lst;
  368. i < canvas->line_cnt; i++, pLS++)
  369. {
  370. /*
  371. * Does this line end off the page?
  372. */
  373. if (pLS->max_y > newY2 && pLS->pos_y < newY2)
  374. newY2 = pLS->pos_y - 1;
  375. }
  376. }
  377. /*
  378. * check each line to see if it is on the 'page'
  379. */
  380. for (i = 0, pLS = canvas->line_lst; i < canvas->line_cnt; i++, pLS++)
  381. {
  382. lnInfo.width = pLS->width;
  383. lnInfo.data = pLS->data;
  384. lnInfo.x2 = pLS->pos_x;
  385. lnInfo.y2 = pLS->pos_y;
  386. /*
  387. * horizontal or vertial line?
  388. */
  389. if (_DtCvLINE_HORZ == pLS->dir)
  390. lnInfo.x2 = pLS->max_x;
  391. else
  392. lnInfo.y2 = pLS->max_y;
  393. /*
  394. * does it fit on the page? Take into account the rendering type.
  395. */
  396. if (pLS->max_y >= y1 && pLS->pos_y <= newY2
  397. && lnInfo.x2 >= x1 && pLS->pos_x <= x2
  398. && (_DtCvRENDER_PARTIAL == flag || pLS->max_y <= newY2))
  399. {
  400. if (pLS->max_y > *ret_y)
  401. *ret_y = pLS->max_y;
  402. (*(canvas->virt_functions.render_elem))(
  403. canvas->client_data, _DtCvLINE_TYPE,
  404. pLS->pos_x, pLS->pos_y, -1, 0, 0,
  405. _DtCvBAD_TYPE, NULL, &lnInfo);
  406. }
  407. /*
  408. * otherwise, would this start the next page?
  409. * make sure this is in the horizontal space.
  410. */
  411. else if (lnInfo.x2 >= x1 && pLS->pos_x <= x2 && pLS->max_y > newY2
  412. && (-1 == *ret_next || *ret_next > pLS->pos_y))
  413. *ret_next = pLS->pos_y;
  414. }
  415. }
  416. } /* End DrawCanvasLines */
  417. /******************************************************************************
  418. * Function: DrawText
  419. *
  420. * Parameters:
  421. * canvas Specifies the canvas on which to render
  422. * the text.
  423. * line Specifies the line in the line table.
  424. * start_x Specifies the starting x position to use
  425. * for selected text. If greater than the
  426. * starting position for the segment, determine
  427. * the closest character to 'start_x' and
  428. * use it.
  429. * end_x Specifies the ending x position to use
  430. * for selected text. If -1, means display
  431. * the entire set of segments.
  432. * old_flag Specifies....
  433. * new_flag Specifies....
  434. *
  435. * Returns: max_x Returns the maximum x unit processed.
  436. *
  437. * Purpose: DrawText draws text segments on one line in the
  438. * line table.
  439. *
  440. *****************************************************************************/
  441. static _DtCvUnit
  442. DrawText(
  443. _DtCanvasStruct *canvas,
  444. _DtCvDspLine *line,
  445. int txt_line,
  446. _DtCvFlags old_flag,
  447. _DtCvFlags new_flag )
  448. {
  449. int len;
  450. int curIdx = 0;
  451. int lastLnk = -1;
  452. int count = line->length;
  453. int start = line->byte_index;
  454. _DtCvUnit xPos;
  455. _DtCvUnit superWidth = 0;
  456. _DtCvUnit superY = 0;
  457. _DtCvUnit subWidth = 0;
  458. _DtCvUnit subY = 0;
  459. _DtCvUnit scriptX = 0;
  460. _DtCvValue lastWasSuper = False;
  461. _DtCvValue lastWasSub = False;
  462. _DtCvValue lastLnkVis = False;
  463. _DtCvSegmentI *pSeg;
  464. xPos = _DtCvGetStartXOfLine(line, &pSeg);
  465. /*
  466. * get the corrected x for links and traversals.
  467. */
  468. xPos = _DtCvAdvanceXOfLine(canvas, pSeg, xPos, &lastLnk, &lastLnkVis);
  469. /*
  470. * take into account the if this is a super or sub script - or not.
  471. */
  472. xPos = _DtCvAdjustForSuperSub(canvas, pSeg, xPos,
  473. &scriptX, &superWidth, &superY,
  474. &subWidth, &subY,
  475. &lastWasSuper, &lastWasSub);
  476. /*
  477. * now process the line
  478. */
  479. while (NULL != pSeg && 0 < count)
  480. {
  481. len = count;
  482. /*
  483. * check for selected and marked text.
  484. */
  485. _DtCvCheckLineMarks(canvas, txt_line, curIdx, count, xPos,
  486. (_DtCvSELECTED_FLAG | _DtCvMARK_FLAG),
  487. &len, &old_flag, &new_flag);
  488. /*
  489. * if this is the last segment(s) of the (un)selection
  490. * set the end flags.
  491. */
  492. if (len == count)
  493. {
  494. new_flag |= (_DtCvTRAVERSAL_END | _DtCvLINK_END);
  495. old_flag |= (_DtCvTRAVERSAL_END | _DtCvLINK_END);
  496. }
  497. /*
  498. * render the segment length returned by _DtCvCheckLineMarks
  499. */
  500. xPos = _DtCvDrawSegments(canvas, *line, pSeg, start, len,
  501. &lastLnk, xPos, xPos,
  502. &scriptX, &superWidth, &superY, &subWidth,
  503. &subY, &lastWasSub, &lastWasSuper,
  504. &lastLnkVis, old_flag, new_flag,
  505. _DtCvBAD_TYPE, NULL);
  506. /*
  507. * decrement the count by the length processed
  508. */
  509. count -= len;
  510. curIdx += len;
  511. if (0 < count)
  512. _DtCvSkipLineChars(canvas, pSeg, start, count + len, len,
  513. &start, &pSeg);
  514. }
  515. return xPos;
  516. } /* End DrawText */
  517. /*****************************************************************************
  518. * Function: IsLineSpecial (
  519. *
  520. * Purpose: Call a virtual function to draw the traversal indicator
  521. *****************************************************************************/
  522. static _DtCvValue
  523. IsLineSpecial (
  524. _DtCvSelectData start,
  525. _DtCvSelectData end,
  526. _DtCvDspLine line,
  527. int line_idx,
  528. int char_idx,
  529. int length,
  530. _DtCvUnit dst_x,
  531. int *ret_len,
  532. _DtCvFlags *ret_flag)
  533. {
  534. _DtCvUnit maxY = line.baseline + line.descent;
  535. _DtCvUnit minY = line.baseline - line.ascent;
  536. _DtCvFlags flag = 0;
  537. /*
  538. * zero out the return flag (which will be a logical OR of
  539. * the mark flags.
  540. */
  541. if (NULL != ret_flag)
  542. *ret_flag = 0;
  543. /*
  544. * initialize the return value to the given inspection length.
  545. */
  546. *ret_len = length;
  547. /*
  548. * is there anything to look at?
  549. */
  550. if (start.y == -1 || maxY < start.y || minY >= end.y)
  551. return False;
  552. /*
  553. * starts the mark/selection?
  554. */
  555. if (line_idx == start.line_idx)
  556. {
  557. /*
  558. * does this segment straddle the start of the mark/selection?
  559. */
  560. if (start.char_idx > char_idx)
  561. {
  562. /*
  563. * draw part(or all) of the segment un-mark/selected.
  564. * never return a value larger than the inspection length!
  565. */
  566. if (start.char_idx < char_idx + length)
  567. *ret_len = start.char_idx - char_idx;
  568. return False;
  569. }
  570. /*
  571. * does this segment start the line? Set the start flag if so.
  572. */
  573. if (start.char_idx == char_idx)
  574. flag |= _DtCvMARK_BEGIN;
  575. /*
  576. * does this line end the mark/selection?
  577. */
  578. if (line_idx == end.line_idx)
  579. {
  580. /*
  581. * does this line straddle the end?
  582. */
  583. if (char_idx >= end.char_idx)
  584. {
  585. /*
  586. * draw this un mark/selected.
  587. * Its after the mark/selected part.
  588. */
  589. return False;
  590. }
  591. if (char_idx + length > end.char_idx)
  592. {
  593. /*
  594. * draw the mark/selected part
  595. */
  596. *ret_len = end.char_idx - char_idx;
  597. flag |= _DtCvMARK_END;
  598. }
  599. }
  600. /*
  601. * draw the current *ret_len as mark/selected
  602. */
  603. }
  604. /*
  605. * does this start the mark/selection?
  606. */
  607. else if (line_idx == end.line_idx)
  608. {
  609. /*
  610. * does not start the mark/selection.
  611. * does end the mark/selection.
  612. */
  613. if (char_idx >= end.char_idx)
  614. return False;
  615. /*
  616. * straddle the end position?
  617. */
  618. if (char_idx + length > end.char_idx)
  619. {
  620. *ret_len = end.char_idx - char_idx;
  621. flag |= _DtCvMARK_END;
  622. }
  623. /*
  624. * draw the current *ret_len as mark/selected
  625. */
  626. }
  627. /*
  628. * start.y != -1
  629. * start.y <= maxY && minY < end.y
  630. */
  631. else if (minY < start.y)
  632. {
  633. /*
  634. * straddles the start y
  635. */
  636. if (dst_x < start.x)
  637. return False;
  638. /*
  639. * dst_x > start.x
  640. */
  641. if (start.y != end.y)
  642. {
  643. if (NULL != ret_flag)
  644. *ret_flag = flag;
  645. return True;
  646. }
  647. /*
  648. * dst_x >= end.x
  649. */
  650. if (dst_x > end.x)
  651. return False;
  652. }
  653. /*
  654. * start.y <= minY and maxY
  655. * minY < end.y
  656. */
  657. else if (end.y <= maxY)
  658. {
  659. /*
  660. * straddles the end y position
  661. */
  662. if (dst_x >= end.x)
  663. return False;
  664. }
  665. /*
  666. * start.y <= minY and maxY
  667. * minY && maxY < end.y
  668. */
  669. if (NULL != ret_flag)
  670. *ret_flag = flag;
  671. return True;
  672. }
  673. /*****************************************************************************
  674. * Function: DrawTraversalIndicator (_DtCanvasStruct *canvas, _DtCvValue flag)
  675. *
  676. * Purpose: (Un)draws the traversal around the currently active link.
  677. *****************************************************************************/
  678. static void
  679. DrawTraversalIndicator (
  680. _DtCanvasStruct *canvas,
  681. _DtCvValue render,
  682. _DtCvValue draw_flag,
  683. _DtCvUnit *ret_x,
  684. _DtCvUnit *ret_y,
  685. _DtCvUnit *ret_baseline,
  686. _DtCvUnit *ret_height)
  687. {
  688. int count;
  689. int len;
  690. int start;
  691. int wrkChr;
  692. int totCnt;
  693. int travIdx = canvas->cur_trav;
  694. int curIdx = 0;
  695. int txtLine = canvas->trav_lst[travIdx].idx;
  696. int linkIndex;
  697. int lstLnk = -1;
  698. _DtCvUnit height = 0;
  699. _DtCvUnit dstX;
  700. _DtCvUnit tmpWidth;
  701. _DtCvUnit superWidth = 0;
  702. _DtCvUnit superY = 0;
  703. _DtCvUnit subWidth = 0;
  704. _DtCvUnit subY = 0;
  705. _DtCvUnit scriptX = 0;
  706. _DtCvFlags oldFlag = 0;
  707. _DtCvFlags newFlag = 0;
  708. _DtCvValue lastWasSub = False;
  709. _DtCvValue lastWasSuper = False;
  710. _DtCvValue lstLnkVis = False;
  711. _DtCvSegmentI *pSeg;
  712. _DtCvSegmentI *tmpSeg;
  713. /*
  714. * determine the flags for rendering.
  715. */
  716. if (draw_flag)
  717. newFlag = _DtCvTRAVERSAL_FLAG;
  718. else
  719. oldFlag = _DtCvTRAVERSAL_FLAG;
  720. /*
  721. * allow traversal to marks.
  722. */
  723. if (_DtCvTraversalMark == canvas->trav_lst[travIdx].type)
  724. {
  725. int markIdx = canvas->trav_lst[travIdx].idx;
  726. if (True == render)
  727. {
  728. oldFlag = oldFlag | _DtCvMARK_FLAG
  729. | _DtCvTRAVERSAL_BEGIN | _DtCvTRAVERSAL_END;
  730. newFlag = newFlag | _DtCvMARK_FLAG
  731. | _DtCvTRAVERSAL_BEGIN | _DtCvTRAVERSAL_END;
  732. if (_DtCvTRUE == canvas->marks[markIdx].on)
  733. {
  734. oldFlag |= _DtCvMARK_ON;
  735. newFlag |= _DtCvMARK_ON;
  736. }
  737. _DtCvDrawAreaWithFlags(canvas,
  738. canvas->marks[markIdx].beg,
  739. canvas->marks[markIdx].end,
  740. oldFlag, newFlag,
  741. _DtCvMARK_TYPE,
  742. canvas->marks[markIdx].client_data);
  743. }
  744. if (ret_height)
  745. *ret_height = canvas->marks[markIdx].end.y -
  746. canvas->marks[markIdx].beg.y +
  747. canvas->txt_lst[canvas->marks[markIdx].end.line_idx].descent +
  748. canvas->txt_lst[canvas->marks[markIdx].beg.line_idx].ascent;
  749. /*
  750. * set some return variables
  751. */
  752. if (ret_x)
  753. *ret_x = canvas->marks[markIdx].beg.x;
  754. if (ret_y)
  755. *ret_y = canvas->marks[markIdx].beg.y -
  756. canvas->txt_lst[canvas->marks[markIdx].beg.line_idx].ascent;
  757. if (ret_baseline)
  758. *ret_baseline = canvas->marks[markIdx].beg.y;
  759. return;
  760. }
  761. /*
  762. * get the link index
  763. */
  764. linkIndex = canvas->trav_lst[travIdx].seg_ptr->link_idx;
  765. /*
  766. * determine the location of the hypertext segment.
  767. */
  768. pSeg = canvas->trav_lst[travIdx].seg_ptr;
  769. start = canvas->txt_lst[txtLine].byte_index;
  770. count = canvas->txt_lst[txtLine].length;
  771. /*
  772. * get the start of the line
  773. */
  774. dstX = _DtCvGetStartXOfLine(&(canvas->txt_lst[txtLine]), &pSeg);
  775. while (pSeg->link_idx != linkIndex)
  776. {
  777. /*
  778. * get the corrected x
  779. */
  780. dstX = _DtCvAdvanceXOfLine (canvas, pSeg, dstX, &lstLnk, &lstLnkVis);
  781. /*
  782. * move the text x position base on if this is a super or
  783. * sub script - or not.
  784. */
  785. dstX = _DtCvAdjustForSuperSub(canvas, pSeg, dstX, &scriptX,
  786. &superWidth, &superY, &subWidth, &subY,
  787. &lastWasSuper, &lastWasSub);
  788. /*
  789. * get the width of the segment.
  790. */
  791. _DtCvGetWidthOfSegment(canvas, pSeg, start, count,
  792. &len, &tmpWidth, NULL);
  793. dstX += tmpWidth;
  794. /*
  795. * update pointers
  796. */
  797. lstLnk = pSeg->link_idx;
  798. count -= len;
  799. curIdx += len;
  800. pSeg = pSeg->next_disp;
  801. start = 0;
  802. }
  803. /*
  804. * set some return variables
  805. */
  806. if (ret_x)
  807. *ret_x = dstX;
  808. if (ret_y)
  809. *ret_y = canvas->txt_lst[txtLine].baseline -
  810. canvas->txt_lst[txtLine].ascent;
  811. if (ret_baseline)
  812. *ret_baseline = canvas->txt_lst[txtLine].baseline;
  813. /*
  814. * start drawing the traversals
  815. */
  816. height = 0;
  817. if (True == render)
  818. {
  819. while (txtLine < canvas->txt_cnt && linkIndex == pSeg->link_idx)
  820. {
  821. /*
  822. * get the corrected x
  823. */
  824. dstX = _DtCvAdvanceXOfLine (canvas,pSeg, dstX, &lstLnk, &lstLnkVis);
  825. /*
  826. * move the text x position base on if this is a super or
  827. * sub script - or not.
  828. */
  829. dstX = _DtCvAdjustForSuperSub(canvas, pSeg, dstX, &scriptX,
  830. &superWidth, &superY, &subWidth, &subY,
  831. &lastWasSuper, &lastWasSub);
  832. /*
  833. * now count up the number of bytes to display for
  834. * the traversal.
  835. */
  836. totCnt = count;
  837. tmpSeg = pSeg;
  838. count = 0;
  839. wrkChr = start;
  840. while (totCnt > 0 && tmpSeg != NULL
  841. && tmpSeg->link_idx == linkIndex)
  842. {
  843. _DtCvGetWidthOfSegment(canvas, tmpSeg, wrkChr,
  844. totCnt, &len, NULL, NULL);
  845. totCnt -= len;
  846. count += len;
  847. wrkChr = 0;
  848. tmpSeg = tmpSeg->next_disp;
  849. }
  850. /*
  851. * set the begin flag.
  852. */
  853. newFlag |= (_DtCvTRAVERSAL_BEGIN | _DtCvLINK_BEGIN);
  854. oldFlag |= (_DtCvTRAVERSAL_BEGIN | _DtCvLINK_BEGIN);
  855. while (count > 0 && pSeg != NULL && pSeg->link_idx == linkIndex)
  856. {
  857. /*
  858. * the original count for the traversal.
  859. */
  860. len = count;
  861. /*
  862. * if there is mark/selected text, determine, how much
  863. */
  864. _DtCvCheckLineMarks(canvas, txtLine, curIdx, count, dstX,
  865. (_DtCvSELECTED_FLAG | _DtCvMARK_FLAG),
  866. &len, &oldFlag, &newFlag);
  867. /*
  868. * if this is the last segment(s) of the traversal
  869. * set the end flags.
  870. */
  871. if (len == count)
  872. {
  873. newFlag |= (_DtCvTRAVERSAL_END | _DtCvLINK_END);
  874. oldFlag |= (_DtCvTRAVERSAL_END | _DtCvLINK_END);
  875. }
  876. /*
  877. * render the segments
  878. */
  879. dstX = _DtCvDrawSegments(canvas, canvas->txt_lst[txtLine],
  880. pSeg, start, len, &lstLnk, dstX, dstX,
  881. &scriptX,&superWidth,&superY,&subWidth,&subY,
  882. &lastWasSub, &lastWasSuper,
  883. &lstLnkVis, oldFlag, newFlag,
  884. _DtCvLINK_TYPE, NULL);
  885. count -= len;
  886. curIdx += len;
  887. if (count > 0)
  888. {
  889. _DtCvSkipLineChars(canvas, pSeg, start, count + len, len,
  890. &start, &pSeg);
  891. newFlag &= ~(_DtCvTRAVERSAL_BEGIN);
  892. oldFlag &= ~(_DtCvTRAVERSAL_BEGIN);
  893. }
  894. }
  895. height += canvas->txt_lst[txtLine].ascent
  896. + canvas->txt_lst[txtLine].descent;
  897. txtLine++;
  898. if (txtLine < canvas->txt_cnt)
  899. {
  900. start = canvas->txt_lst[txtLine].byte_index;
  901. count = canvas->txt_lst[txtLine].length;
  902. curIdx = 0;
  903. superWidth = 0;
  904. superY = 0;
  905. subWidth = 0;
  906. subY = 0;
  907. scriptX = 0;
  908. lstLnk = -1;
  909. lastWasSuper = False;
  910. lastWasSub = False;
  911. lstLnkVis = False;
  912. /*
  913. * get the correct x
  914. */
  915. dstX = _DtCvGetStartXOfLine(&(canvas->txt_lst[txtLine]), &pSeg);
  916. }
  917. }
  918. }
  919. if (ret_height)
  920. *ret_height = height;
  921. } /* End DrawTraversalIndicator */
  922. /*****************************************************************************
  923. * Semi-Public Functions
  924. *****************************************************************************/
  925. /*****************************************************************************
  926. * Function: _DtCvGetSearchLineMetrics (
  927. *
  928. * Purpose: gets the text line metrics for the search item.
  929. *****************************************************************************/
  930. int
  931. _DtCvGetSearchLineMetrics(_DtCvHandle handle, int idx, _DtCvUnit* baseline,
  932. _DtCvUnit* descent, _DtCvUnit* ascent)
  933. {
  934. int ret = 0;
  935. _DtCanvasStruct* canvas = (_DtCanvasStruct*)handle;
  936. _DtCvDspLine* line;
  937. if (idx < 0 || idx >= canvas->search_cnt)
  938. return -1;
  939. line = &(canvas->txt_lst[canvas->searchs[idx].idx]);
  940. *baseline = line->baseline;
  941. *descent = line->descent;
  942. *ascent = line->ascent;
  943. return ret;
  944. }
  945. /*****************************************************************************
  946. * Function: _DtCvCheckInfringement (
  947. *
  948. * Purpose: Checks to see if one object infringes vertically on another
  949. * object.
  950. *****************************************************************************/
  951. _DtCvStatus
  952. _DtCvCheckInfringement (
  953. _DtCvUnit tst_top,
  954. _DtCvUnit tst_bot,
  955. _DtCvUnit obj_top,
  956. _DtCvUnit obj_bot)
  957. {
  958. _DtCvStatus result = False;
  959. /*
  960. * check to see if the object is to the left or right of the test
  961. * object and that it 'infringes' on the vertical space of the test
  962. * object.
  963. *
  964. * I.e. ----obj_top------
  965. * | | ----tst_top----
  966. * ----obj_bot------ | |
  967. * ----tst_bot----
  968. *
  969. * I.e. ----tst_top----
  970. * ----obj_top------- | |
  971. * | | ----tst_bot----
  972. * ----obj_bot-------
  973. *
  974. * I.e. ----obj_top------
  975. * | | ----tst_top----
  976. * | | | |
  977. * | | ----tst_bot----
  978. * ----obj_bot------
  979. *
  980. * I.e. ----tst_top----
  981. * ----obj_top------- | |
  982. * | | | |
  983. * ----obj_bot------- | |
  984. * ----tst_bot----
  985. */
  986. if ((obj_top < tst_top && tst_top < obj_bot)
  987. || (obj_top < tst_bot && tst_bot < obj_bot)
  988. || (obj_top <= tst_top && tst_bot <= obj_bot)
  989. || (tst_top < obj_top && obj_bot < tst_bot))
  990. result = True;
  991. return result;
  992. }
  993. /*****************************************************************************
  994. * Function: _DtCvCheckLineMarks (
  995. *
  996. * Parameters:
  997. * canvas Specifies the canvas to check for
  998. * marks and/or selections.
  999. * line_idx Specifies the line index into the
  1000. * list of text lines in the canvas.
  1001. * char_idx Specifies the starting character index
  1002. * in the text line.
  1003. * length Specifies the length of the text line
  1004. * to consider.
  1005. * dst_x Specifies the x position of the
  1006. * starting character in the text line.
  1007. * check_flags Specifies which type to look for -
  1008. * selection, marks or both.
  1009. * ret_len Returns the length of the text line
  1010. * starting at the starting character
  1011. * index for which the flags returned
  1012. * in ret_old and ret_new are valid.
  1013. * ret_old, ret_new
  1014. * Returns the values in ret_old and ret_new
  1015. * and may add _DtCvSELECTED_FLAG and/or
  1016. * _DtCvMARK_FLAG.
  1017. *
  1018. * Purpose: Find out how much of the line is (un)marked in some way.
  1019. *****************************************************************************/
  1020. void
  1021. _DtCvCheckLineMarks (
  1022. _DtCanvasStruct *canvas,
  1023. int line_idx,
  1024. int char_idx,
  1025. int length,
  1026. _DtCvUnit dst_x,
  1027. _DtCvFlags check_flags,
  1028. int *ret_len,
  1029. _DtCvFlags *ret_old,
  1030. _DtCvFlags *ret_new)
  1031. {
  1032. int i;
  1033. _DtCvFlags flag = 0;
  1034. /*
  1035. * check the selection
  1036. */
  1037. if ((check_flags & _DtCvSELECTED_FLAG) && canvas->select_start.y != -1)
  1038. {
  1039. _DtCvSelectData start = canvas->select_start;
  1040. _DtCvSelectData end = canvas->select_end;
  1041. /*
  1042. * check to see if we need to switch the selection points
  1043. */
  1044. if (start.y > end.y || (start.y == end.y && start.x > end.x))
  1045. {
  1046. end = canvas->select_start;
  1047. start = canvas->select_end;
  1048. }
  1049. /*
  1050. * clear the selected flag
  1051. */
  1052. *ret_old &= ~(_DtCvSELECTED_FLAG);
  1053. *ret_new &= ~(_DtCvSELECTED_FLAG);
  1054. if (IsLineSpecial(start, end,
  1055. canvas->txt_lst[line_idx], line_idx,
  1056. char_idx, length, dst_x,
  1057. &length, NULL))
  1058. {
  1059. /*
  1060. * set the selected flag.
  1061. */
  1062. *ret_old = *ret_old | _DtCvSELECTED_FLAG;
  1063. *ret_new = *ret_new | _DtCvSELECTED_FLAG;
  1064. }
  1065. }
  1066. if ((check_flags & _DtCvMARK_FLAG) && 0 < canvas->mark_cnt)
  1067. {
  1068. /*
  1069. * strip the mark flags from the old and new flags
  1070. */
  1071. *ret_old &= ~(_DtCvMARK_FLAG | _DtCvMARK_BEGIN |
  1072. _DtCvMARK_END | _DtCvMARK_ON);
  1073. *ret_new &= ~(_DtCvMARK_FLAG | _DtCvMARK_BEGIN |
  1074. _DtCvMARK_END | _DtCvMARK_ON);
  1075. /*
  1076. * now add the correct flags into the old/new flags
  1077. */
  1078. for (i = 0; i < canvas->mark_cnt; i++)
  1079. {
  1080. if (IsLineSpecial(canvas->marks[i].beg, canvas->marks[i].end,
  1081. canvas->txt_lst[line_idx], line_idx,
  1082. char_idx, length, dst_x,
  1083. &length, &flag))
  1084. {
  1085. /*
  1086. * A false return from IsLineSpecial means that 'length'
  1087. * is outside this mark.
  1088. *
  1089. * When true, it means that some part of this mark will
  1090. * be rendered on the call. Therefore set the mark flag
  1091. * and any other flags returned and check for mark 'on'.
  1092. */
  1093. if (_DtCvTRUE == canvas->marks[i].on)
  1094. flag |= _DtCvMARK_ON;
  1095. *ret_old = *ret_old | _DtCvMARK_FLAG | flag;
  1096. *ret_new = *ret_new | _DtCvMARK_FLAG | flag;
  1097. }
  1098. }
  1099. }
  1100. /*
  1101. * return the next length that is marked/unmarked in someway.
  1102. */
  1103. *ret_len = length;
  1104. }
  1105. /******************************************************************************
  1106. * Function: _DtCvSkipLineChars
  1107. *
  1108. * Parameters:
  1109. * canvas Specifies the canvas on which to render
  1110. * the text.
  1111. *
  1112. * Purpose: Given a length, skip ahead that number of 'characters' on
  1113. * the line.
  1114. *****************************************************************************/
  1115. void
  1116. _DtCvSkipLineChars(
  1117. _DtCanvasStruct *canvas,
  1118. _DtCvSegmentI *p_seg,
  1119. int start,
  1120. int max_cnt,
  1121. int use_len,
  1122. int *ret_start,
  1123. _DtCvSegmentI **ret_seg)
  1124. {
  1125. int len;
  1126. /*
  1127. * not all of the traversal line was displayed because
  1128. * part of it is selected. So skip what's been rendered,
  1129. * and do it again.
  1130. */
  1131. while (use_len > 0)
  1132. {
  1133. /*
  1134. * get the byte length of the segment processed.
  1135. */
  1136. _DtCvGetWidthOfSegment(canvas, p_seg, start, max_cnt, &len, NULL, NULL);
  1137. /*
  1138. * increment the start index by the number of total
  1139. * bytes processed. If this is more that what is in
  1140. * the segment, then the if stmt will catch this and
  1141. * set the start index to zero.
  1142. */
  1143. if (len > use_len)
  1144. {
  1145. len = use_len;
  1146. start += len;
  1147. }
  1148. else /* if (len <= use_len) */
  1149. {
  1150. start = 0;
  1151. p_seg = p_seg->next_disp;
  1152. }
  1153. /*
  1154. * reduce the total number of bytes
  1155. * processed by the number in this segment.
  1156. */
  1157. use_len -= len;
  1158. max_cnt -= len;
  1159. }
  1160. *ret_start = start;
  1161. *ret_seg = p_seg;
  1162. }
  1163. /******************************************************************************
  1164. * Function: _DtCvClearInternalUse
  1165. *
  1166. * Init every internal_use pointer on containers to NULL.
  1167. *****************************************************************************/
  1168. void
  1169. _DtCvClearInternalUse(
  1170. _DtCvSegmentI *list,
  1171. _DtCvStatus flag)
  1172. {
  1173. while (NULL != list)
  1174. {
  1175. /*
  1176. * initialize the internal variables
  1177. */
  1178. list->internal_use = (void *) -1;
  1179. if (_DtCvIsSegContainer(list))
  1180. _DtCvClearInternalUse(_DtCvContainerListOfSeg(list), flag);
  1181. list = list->next_seg;
  1182. }
  1183. }
  1184. /******************************************************************************
  1185. * Function: _DtCvGetCharIdx
  1186. *
  1187. * Parameters:
  1188. * canvas Specifies the canvas on which to render
  1189. * the text.
  1190. * line Specifies the line in the line table.
  1191. * find_x Specifies the x position of the character.
  1192. *
  1193. * Returns: ?? Returns the idx of the character.
  1194. *
  1195. * Purpose:
  1196. *****************************************************************************/
  1197. int
  1198. _DtCvGetCharIdx(
  1199. _DtCanvasStruct *canvas,
  1200. _DtCvDspLine line,
  1201. _DtCvUnit find_x)
  1202. {
  1203. void *pChar;
  1204. _DtCvValue done = FALSE;
  1205. _DtCvValue lastLinkVisible = FALSE;
  1206. int count = line.length;
  1207. int start = line.byte_index;
  1208. int len = -1;
  1209. int lnkInd = -1;
  1210. _DtCvUnit segWidth;
  1211. _DtCvUnit xPos;
  1212. _DtCvSegmentI *pSeg;
  1213. xPos = _DtCvGetStartXOfLine(&line, &pSeg);
  1214. /*
  1215. * check to see if the start is in the middle of the line.
  1216. * If so, bump the x position and start indexes to the
  1217. * correct locations.
  1218. */
  1219. while (!done && find_x > xPos && count > 0)
  1220. {
  1221. xPos = _DtCvAdvanceXOfLine(canvas, pSeg, xPos,
  1222. &lnkInd, &lastLinkVisible);
  1223. if (xPos < find_x)
  1224. {
  1225. /*
  1226. * advance the pointer by the width
  1227. */
  1228. _DtCvGetWidthOfSegment(canvas, pSeg, start, count,
  1229. &len, &segWidth, NULL);
  1230. if (segWidth + xPos <= find_x)
  1231. {
  1232. xPos += segWidth;
  1233. pSeg = pSeg->next_disp;
  1234. count -= len;
  1235. start = 0;
  1236. }
  1237. else /* if (xPos < find_x && find_x < xPos + segWidth) */
  1238. {
  1239. if (_DtCvIsSegString(pSeg))
  1240. {
  1241. pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
  1242. _DtCvIsSegWideChar(pSeg), start);
  1243. len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(pSeg));
  1244. if (len > count)
  1245. len = count;
  1246. count -= FindChar(canvas, pSeg, pChar, len,
  1247. find_x - xPos, NULL);
  1248. }
  1249. done = True;
  1250. }
  1251. }
  1252. len = line.length - count;
  1253. }
  1254. return len;
  1255. }
  1256. /*****************************************************************************
  1257. * Function: _DtCvGetStartXOfLine
  1258. *
  1259. * Purpose: Get the starting 'x' of the specified line
  1260. * Does *not* take into account traversal or link info.
  1261. *****************************************************************************/
  1262. _DtCvUnit
  1263. _DtCvGetStartXOfLine (
  1264. _DtCvDspLine *line,
  1265. _DtCvSegmentI **p_seg)
  1266. {
  1267. *p_seg = line->seg_ptr;
  1268. return line->text_x;
  1269. }
  1270. /*****************************************************************************
  1271. * Function: _DtCvAdvanceXOfLine
  1272. *
  1273. * Purpose: Move the 'x' to after the traversal and link info.
  1274. *****************************************************************************/
  1275. _DtCvUnit
  1276. _DtCvAdvanceXOfLine (
  1277. _DtCanvasStruct *canvas,
  1278. _DtCvSegmentI *p_seg,
  1279. _DtCvUnit x_pos,
  1280. int *link_idx,
  1281. _DtCvValue *link_flag)
  1282. {
  1283. _DtCvValue junk;
  1284. /*
  1285. * take into account the link before and after space
  1286. */
  1287. junk = _DtCvIsSegVisibleLink(p_seg);
  1288. *link_flag = _DtCvModifyXpos (canvas->link_info, p_seg, junk,
  1289. *link_flag, *link_idx, &x_pos);
  1290. /*
  1291. * take into account the traversal before and after space
  1292. */
  1293. junk = _DtCvIsSegALink(p_seg);
  1294. (void) _DtCvModifyXpos (canvas->traversal_info, p_seg, junk,
  1295. ((_DtCvValue) True), *link_idx, &x_pos);
  1296. *link_idx = p_seg->link_idx;
  1297. return x_pos;
  1298. }
  1299. /******************************************************************************
  1300. * Function: _DtCvGetWidthOfSegment
  1301. *
  1302. * DetermineWidthOfSegment determines the width of the segment.
  1303. * The segment must have been already initialized with the correct
  1304. * font (for strings), the spc resolve, the graphic loaded, etc.
  1305. *
  1306. *****************************************************************************/
  1307. void
  1308. _DtCvGetWidthOfSegment(
  1309. _DtCanvasStruct *canvas,
  1310. _DtCvSegmentI *p_seg,
  1311. int start,
  1312. int max_cnt,
  1313. int *ret_cnt,
  1314. _DtCvUnit *ret_w,
  1315. _DtCvValue *ret_trimmed)
  1316. {
  1317. void *pChar;
  1318. /*
  1319. * return the width of the segment.
  1320. */
  1321. *ret_cnt = 0;
  1322. if (ret_w != NULL)
  1323. *ret_w = 0;
  1324. if (ret_trimmed != NULL)
  1325. *ret_trimmed = False;
  1326. if (!(_DtCvIsSegNoop(p_seg)))
  1327. {
  1328. if (_DtCvIsSegRegion(p_seg))
  1329. {
  1330. *ret_cnt = 1;
  1331. if (ret_w != NULL)
  1332. *ret_w = _DtCvWidthOfRegionSeg(p_seg);
  1333. }
  1334. else
  1335. {
  1336. pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(p_seg),
  1337. _DtCvIsSegWideChar(p_seg), start);
  1338. *ret_cnt = _DtCvStrLen (pChar, _DtCvIsSegWideChar(p_seg));
  1339. if (*ret_cnt > max_cnt)
  1340. {
  1341. *ret_cnt = max_cnt;
  1342. if (ret_trimmed != NULL)
  1343. *ret_trimmed = True;
  1344. }
  1345. /*
  1346. * determine the width of the string.
  1347. */
  1348. if (ret_w != NULL)
  1349. *ret_w = _DtCvGetStringWidth(canvas, p_seg,pChar,*ret_cnt);
  1350. }
  1351. }
  1352. }
  1353. /******************************************************************************
  1354. * Function: _DtCvModifyXpos
  1355. *****************************************************************************/
  1356. _DtCvValue
  1357. _DtCvModifyXpos (
  1358. _DtCvSpaceMetrics info,
  1359. _DtCvSegmentI *seg,
  1360. _DtCvValue tst_result,
  1361. _DtCvValue cur_flag,
  1362. int last_idx,
  1363. _DtCvUnit *x)
  1364. {
  1365. int addx = 0;
  1366. /*
  1367. * take into account the link before and after space
  1368. */
  1369. if (tst_result)
  1370. {
  1371. /*
  1372. * Ignore if the same link
  1373. */
  1374. if (last_idx != seg->link_idx)
  1375. {
  1376. /*
  1377. * if one link followed by another add the space after.
  1378. */
  1379. if (last_idx != -1)
  1380. addx = info.space_after;
  1381. /*
  1382. * add the space before the link
  1383. */
  1384. addx += info.space_before;
  1385. }
  1386. cur_flag = True;
  1387. }
  1388. else
  1389. {
  1390. if (last_idx != -1 && cur_flag == True)
  1391. addx = info.space_after;
  1392. cur_flag = False;
  1393. }
  1394. *x += addx;
  1395. return cur_flag;
  1396. }
  1397. /*****************************************************************************
  1398. * Function: _DtCvAdjustForSuperSub
  1399. *
  1400. * Parameters:
  1401. * canvas Specifies the canvas.
  1402. * start_x Specifies the current text x position.
  1403. * script_x Specifies the current super and sub
  1404. * scripting x position. Returns the same
  1405. * value as start_x if the segment is not a
  1406. * super or sub script.
  1407. * super_width Specifies the width of the previously
  1408. * rendered super script. Set to 0 if the
  1409. * next segment is not a super or sub
  1410. * script.
  1411. * super_y Specifies the y offset for super
  1412. * scripts. Set to a new value if the last
  1413. * segment was not a super or sub script.
  1414. * sub_width Specifies the width of the previously
  1415. * rendered sub script. Set to 0 if the
  1416. * next segment is not a super or sub
  1417. * script.
  1418. * sub_y Specifies the y offset for sub scripts.
  1419. * Set to a new value if the last segment
  1420. * was not a super or sub script.
  1421. * last_was_super Specifies if the last item was a super
  1422. * script. Set to False if the segment
  1423. * is not a super or sub script.
  1424. * last_was_sub Specifies if the last item was a sub
  1425. * script. Set to False if the segment
  1426. * is not a super or sub script.
  1427. * Returns: new text x positon.
  1428. *
  1429. * Purpose: Determines the super and sub scripting positions for text.
  1430. * If the last item was not a script, then the base offset for
  1431. * scripting (script_x) is moved to start_x. If the current
  1432. * item is a string, its scripting y position is determined
  1433. * (super_y and sub_y). If the new item is a super or sub
  1434. * script, the next text placement (start_x) is moved to after
  1435. * the script_x plus the super or sub script size currently
  1436. * active(super_width and sub_width). Otherwise, the the flags
  1437. * are set to false and the widths are set to 0.
  1438. *
  1439. *****************************************************************************/
  1440. _DtCvUnit
  1441. _DtCvAdjustForSuperSub(
  1442. _DtCanvasStruct *canvas,
  1443. _DtCvSegmentI *pSeg,
  1444. _DtCvUnit start_x,
  1445. _DtCvUnit *script_x,
  1446. _DtCvUnit *super_width,
  1447. _DtCvUnit *super_y,
  1448. _DtCvUnit *sub_width,
  1449. _DtCvUnit *sub_y,
  1450. _DtCvValue *last_was_super,
  1451. _DtCvValue *last_was_sub)
  1452. {
  1453. /*
  1454. * if the last item was not a super or sub script,
  1455. * move the script x to the end of the last output.
  1456. */
  1457. if (!(*last_was_super || *last_was_sub))
  1458. *script_x = start_x;
  1459. /*
  1460. * check for super and sub scripts.
  1461. * adjust text x positioning accordingly.
  1462. */
  1463. if (_DtCvIsSegSuperScript(pSeg))
  1464. {
  1465. start_x = *script_x + *super_width;
  1466. *last_was_super = True;
  1467. }
  1468. else if (_DtCvIsSegSubScript(pSeg))
  1469. {
  1470. start_x = *script_x + *sub_width;
  1471. *last_was_sub = True;
  1472. }
  1473. else if (*last_was_super || *last_was_sub)
  1474. {
  1475. *sub_width = 0;
  1476. *super_width = 0;
  1477. *last_was_super = False;
  1478. *last_was_sub = False;
  1479. }
  1480. /*
  1481. * if this wasn't a super or sub script, find out where
  1482. * they get placed on this string.
  1483. */
  1484. if (!(*last_was_super || *last_was_sub))
  1485. {
  1486. if (_DtCvIsSegString(pSeg))
  1487. _DtCvFontMetrics (canvas,_DtCvFontOfStringSeg(pSeg),
  1488. NULL, NULL, NULL, super_y, sub_y);
  1489. else if (_DtCvIsSegRegion(pSeg))
  1490. {
  1491. *super_y = _DtCvHeightOfRegionSeg(pSeg) * 4 / 10;
  1492. *sub_y = *super_y;
  1493. }
  1494. }
  1495. return start_x;
  1496. }
  1497. /******************************************************************************
  1498. * Function: _DtCvDrawSegments
  1499. *
  1500. * Parameters:
  1501. * canvas Specifies the canvas on which to render
  1502. * the text.
  1503. * line Specifies the line metrics.
  1504. * p_seg Specifies the starting segment.
  1505. * start_char Specifies the starting index in a string
  1506. * segment. 0 for all others.
  1507. * count Specifies the number of characters
  1508. * (including special characters to
  1509. * render).
  1510. * prev_lnk Indicates the previous link index. Used
  1511. * to calculate extra spacing needed for
  1512. * traversal and link markup.
  1513. * txt_x Specifies the starting x of the
  1514. * segment(s). This does *NOT* take into
  1515. * account traversal or link spacing. This
  1516. * routine will do that. This is so
  1517. * selected links will have correct spacing
  1518. * indicated.
  1519. * sel_x Specifies where the selection x position
  1520. * begins. Usually it equals txt_x, but
  1521. * sometimes it will be less than it to
  1522. * indicate blank space has been selected.
  1523. * super_width Specifies the last super script x offset.
  1524. * super_y Specifies the last super script y offset.
  1525. * sub_width Specifies the last sub script x offset.
  1526. * sub_y Specifies the last sub script y offset.
  1527. * last_was_sub Specifies if the last element was a
  1528. * subscript.
  1529. * last_was_super Specifies if the last element was a
  1530. * superscript.
  1531. * last_was_vis Specifies if the last element was a
  1532. * visible hypertext link.
  1533. * old_flag Specifies what the line use to look like.
  1534. * new_flag Specifies what the line is to look like.
  1535. *
  1536. * Returns: txt_x Returns the maximum x unit processed.
  1537. *
  1538. * Purpose: _DtCvDrawSegments draws one or more segments based on
  1539. * the count passed in.
  1540. *
  1541. * This routine adds CELink to new_flag when rendering segments
  1542. * that are hypertext links. At the same time it will
  1543. * determine the correct window hint and may place in old_flag
  1544. * and new_flag either _DtCvLINK_POP_UP or _DtCvLINK_NEW_WINDOW.
  1545. *
  1546. * This routine strips the _DtCvTRAVERSAL_END from old_flag and
  1547. * new_flag (based on what's in new_flag). It will restore
  1548. * these flags (if specified) when it renders the last element
  1549. * in the count sequence.
  1550. *
  1551. *****************************************************************************/
  1552. _DtCvUnit
  1553. _DtCvDrawSegments(
  1554. _DtCanvasStruct *canvas,
  1555. _DtCvDspLine line,
  1556. struct _dtCvSegment *p_seg,
  1557. int start_char,
  1558. int count,
  1559. int *prev_lnk,
  1560. _DtCvUnit txt_x,
  1561. _DtCvUnit sel_x,
  1562. _DtCvUnit *script_x,
  1563. _DtCvUnit *super_width,
  1564. _DtCvUnit *super_y,
  1565. _DtCvUnit *sub_width,
  1566. _DtCvUnit *sub_y,
  1567. _DtCvValue *last_was_sub,
  1568. _DtCvValue *last_was_super,
  1569. _DtCvValue *last_link_vis,
  1570. _DtCvFlags old_flag,
  1571. _DtCvFlags new_flag,
  1572. _DtCvElemType trav_type,
  1573. _DtCvPointer trav_data )
  1574. {
  1575. int linkType = 0;
  1576. int len;
  1577. short cropped = _DtCvFALSE;
  1578. short image_offset = _DtCvFALSE;
  1579. _DtCvUnit segWidth;
  1580. _DtCvUnit yPos;
  1581. void *pChar;
  1582. _DtCvFlags saveEnd = new_flag &
  1583. (_DtCvTRAVERSAL_END | _DtCvLINK_END | _DtCvMARK_END);
  1584. _DtCvElemType elemType;
  1585. _DtCvRenderInfo posInfo;
  1586. _DtCvStringInfo strInfo;
  1587. /*
  1588. * skip any leading no-op lines
  1589. */
  1590. while (p_seg != NULL && _DtCvIsSegNoop(p_seg))
  1591. {
  1592. start_char = 0;
  1593. p_seg = p_seg->next_disp;
  1594. }
  1595. /*
  1596. * strip the any end info from the flags.
  1597. * it will be put back on with the last element that makes up the count.
  1598. */
  1599. old_flag &= ~saveEnd;
  1600. new_flag &= ~saveEnd;
  1601. /*
  1602. * now process the segments included in 'count'
  1603. */
  1604. while (p_seg != NULL && count > 0)
  1605. {
  1606. /*
  1607. * reset the baseline.
  1608. * when processing super or sub scripts, this gets changed.
  1609. */
  1610. yPos = line.baseline;
  1611. /*
  1612. * take into account the visible link and traversal info.
  1613. */
  1614. txt_x = _DtCvAdvanceXOfLine(canvas, p_seg, txt_x,
  1615. prev_lnk, last_link_vis);
  1616. /*
  1617. * check for super and sub scripts.
  1618. * adjust text x positioning accordingly.
  1619. */
  1620. txt_x = _DtCvAdjustForSuperSub(canvas, p_seg, txt_x,
  1621. script_x, super_width, super_y,
  1622. sub_width, sub_y,
  1623. last_was_super, last_was_sub);
  1624. if (sel_x > txt_x)
  1625. sel_x = txt_x;
  1626. /*
  1627. * set visible link indicator flags
  1628. */
  1629. _DtCvClearLinkFlags(old_flag);
  1630. _DtCvClearLinkFlags(new_flag);
  1631. /*
  1632. * is this a visible link?
  1633. */
  1634. if (_DtCvIsSegVisibleLink(p_seg))
  1635. {
  1636. /*
  1637. * visible link - set the flags.
  1638. */
  1639. new_flag |= _DtCvLINK_FLAG;
  1640. old_flag |= _DtCvLINK_FLAG;
  1641. /*
  1642. * is this the start of a new link? If so, set the begin flag.
  1643. */
  1644. if (*prev_lnk != p_seg->link_idx)
  1645. {
  1646. new_flag |= _DtCvLINK_BEGIN;
  1647. old_flag |= _DtCvLINK_BEGIN;
  1648. }
  1649. /*
  1650. * get the link type and set the window hint.
  1651. */
  1652. linkType = _DtLinkDbGetLinkType(canvas->link_data,p_seg->link_idx);
  1653. switch (_DtLinkDbGetHint(canvas->link_data, p_seg->link_idx))
  1654. {
  1655. case _DtCvWindowHint_PopupWindow:
  1656. new_flag |= _DtCvLINK_POP_UP;
  1657. old_flag |= _DtCvLINK_POP_UP;
  1658. break;
  1659. case _DtCvWindowHint_NewWindow:
  1660. new_flag |= _DtCvLINK_NEW_WINDOW;
  1661. old_flag |= _DtCvLINK_NEW_WINDOW;
  1662. break;
  1663. }
  1664. }
  1665. /*
  1666. * rememeber this link index.
  1667. */
  1668. *prev_lnk = p_seg->link_idx;
  1669. /*
  1670. * set the search flag
  1671. */
  1672. _DtCvClearSearchFlags(old_flag);
  1673. _DtCvClearSearchFlags(new_flag);
  1674. old_flag |= (p_seg->type & _DtCvSEARCH_FLAG);
  1675. new_flag |= (p_seg->type & _DtCvSEARCH_FLAG);
  1676. if (0 == start_char)
  1677. {
  1678. _DtCvSetSearchBegin(old_flag, p_seg);
  1679. _DtCvSetSearchBegin(new_flag, p_seg);
  1680. }
  1681. old_flag &= ~_DtCvAPP_FLAG2;
  1682. new_flag &= ~_DtCvAPP_FLAG2;
  1683. old_flag |= p_seg->type & _DtCvAPP_FLAG2;
  1684. new_flag |= p_seg->type & _DtCvAPP_FLAG2;
  1685. old_flag &= ~(_DtCvAPP_FLAG3 | _DtCvAPP_FLAG4);
  1686. new_flag &= ~(_DtCvAPP_FLAG3 | _DtCvAPP_FLAG4);
  1687. /*
  1688. * init some variables
  1689. */
  1690. segWidth = 0;
  1691. len = 0;
  1692. /*
  1693. * adjust the yPos for sub/superscripts.
  1694. */
  1695. if (_DtCvIsSegSuperScript(p_seg))
  1696. yPos -= *super_y;
  1697. else if (_DtCvIsSegSubScript(p_seg))
  1698. yPos += *sub_y;
  1699. elemType = -1;
  1700. switch (_DtCvPrimaryTypeOfSeg(p_seg))
  1701. {
  1702. case _DtCvSTRING:
  1703. /*
  1704. * set the type
  1705. */
  1706. elemType = _DtCvSTRING_TYPE;
  1707. /*
  1708. * get the string and its length.
  1709. */
  1710. pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(p_seg),
  1711. _DtCvIsSegWideChar(p_seg), start_char);
  1712. len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(p_seg));
  1713. /*
  1714. * if length of the string is longer than we want to
  1715. * output, crop.
  1716. */
  1717. if (len > count)
  1718. {
  1719. len = count;
  1720. cropped = _DtCvTRUE;
  1721. }
  1722. /*
  1723. * initialize the string structure.
  1724. */
  1725. strInfo.string = pChar;
  1726. strInfo.byte_len = len;
  1727. strInfo.wc = _DtCvIsSegWideChar(p_seg);
  1728. strInfo.font_ptr = _DtCvFontOfStringSeg(p_seg);
  1729. strInfo.csd = p_seg->client_use;
  1730. /*
  1731. * now get the width of the string to update the x positions
  1732. */
  1733. segWidth = _DtCvGetStringWidth(canvas, p_seg, pChar, len);
  1734. /*
  1735. * attach the string information to the position info.
  1736. */
  1737. posInfo.info = &strInfo;
  1738. /*
  1739. * reset starting index.
  1740. */
  1741. start_char = 0;
  1742. break;
  1743. case _DtCvREGION:
  1744. /*
  1745. * set the type, length and width
  1746. */
  1747. elemType = _DtCvREGION_TYPE;
  1748. len = 1;
  1749. segWidth = _DtCvWidthOfRegionSeg(p_seg);
  1750. /*
  1751. * attach the region information to the position info.
  1752. */
  1753. posInfo.info = _DtCvInfoOfRegionSeg(p_seg);
  1754. break;
  1755. }
  1756. /*
  1757. * do we have valid information?
  1758. */
  1759. if (-1 != elemType)
  1760. {
  1761. /*
  1762. * now set up the position information
  1763. */
  1764. posInfo.box_x = sel_x;
  1765. posInfo.box_y = line.baseline - line.ascent;
  1766. posInfo.box_height = line.ascent + line.descent + 1;
  1767. posInfo.box_width = segWidth;
  1768. /*
  1769. * if this is the last segment to be rendered,
  1770. * restore the end flags.
  1771. */
  1772. if (len == count)
  1773. {
  1774. new_flag |= saveEnd;
  1775. old_flag |= saveEnd;
  1776. }
  1777. /*
  1778. * if the item (string) was not cropped, set the Search end
  1779. * flag accordingly.
  1780. */
  1781. if (_DtCvFALSE == cropped)
  1782. {
  1783. _DtCvSetSearchEnd(old_flag, p_seg);
  1784. _DtCvSetSearchEnd(new_flag, p_seg);
  1785. if (new_flag & _DtCvSEARCH_END && new_flag & _DtCvAPP_FLAG2 &&
  1786. !(new_flag & _DtCvSELECTED_FLAG)) {
  1787. new_flag |= _DtCvAPP_FLAG4;
  1788. }
  1789. }
  1790. if (image_offset == _DtCvTRUE) {
  1791. old_flag |= _DtCvAPP_FLAG3;
  1792. new_flag |= _DtCvAPP_FLAG3;
  1793. image_offset = _DtCvFALSE;
  1794. }
  1795. /*
  1796. * render the element
  1797. */
  1798. if (NULL != canvas->virt_functions.render_elem)
  1799. (*(canvas->virt_functions.render_elem))(
  1800. canvas->client_data, elemType,
  1801. txt_x, yPos,
  1802. linkType, old_flag, new_flag,
  1803. trav_type, trav_data, &posInfo);
  1804. if (cropped == _DtCvFALSE && new_flag & _DtCvSEARCH_END
  1805. && new_flag & _DtCvAPP_FLAG2
  1806. && !(new_flag & _DtCvSELECTED_FLAG))
  1807. image_offset = _DtCvTRUE;
  1808. }
  1809. /*
  1810. * strip the any begin flags.
  1811. */
  1812. _DtCvRemoveBeginFlags(old_flag);
  1813. _DtCvRemoveBeginFlags(new_flag);
  1814. /*
  1815. * take into account subscripting and superscripting.
  1816. */
  1817. if (_DtCvIsSegSuperScript(p_seg))
  1818. *super_width += segWidth;
  1819. else if (_DtCvIsSegSubScript(p_seg))
  1820. *sub_width += segWidth;
  1821. /*
  1822. * adjust the pointers
  1823. */
  1824. txt_x += segWidth;
  1825. sel_x = txt_x;
  1826. count -= len;
  1827. p_seg = p_seg->next_disp;
  1828. }
  1829. return txt_x;
  1830. } /* End _DtCvDrawSegments */
  1831. /*****************************************************************************
  1832. * Public Functions
  1833. *****************************************************************************/
  1834. /*****************************************************************************
  1835. * Function: _DtCvHandle _DtCanvasCreate (_DtCvVirtualInfo virt_info);
  1836. *
  1837. * Parameters:
  1838. * virt_info Specifies the virtual functions to attach
  1839. * to the created canvas.
  1840. *
  1841. * Returns: A handle to the canvas or NULL if an error occurs.
  1842. *
  1843. * Purpose: Create a canvas and attach the appropriate virtual functions
  1844. * to the canvas.
  1845. *****************************************************************************/
  1846. _DtCvHandle
  1847. _DtCanvasCreate (
  1848. _DtCvVirtualInfo virt_info,
  1849. _DtCvPointer client_data)
  1850. {
  1851. _DtCanvasStruct *newCanvas;
  1852. newCanvas = (_DtCanvasStruct *) malloc (sizeof (_DtCanvasStruct));
  1853. if (newCanvas == NULL)
  1854. return NULL;
  1855. *newCanvas = DefaultCanvas;
  1856. newCanvas->virt_functions = virt_info;
  1857. newCanvas->client_data = client_data;
  1858. newCanvas->mb_length = MB_CUR_MAX;
  1859. /*
  1860. * load the metrics
  1861. */
  1862. _DtCanvasLoadMetrics((_DtCvHandle)newCanvas);
  1863. return ((_DtCvHandle)(newCanvas));
  1864. } /* End _DtCanvasCreate */
  1865. void _DtCanvasLoadMetrics(_DtCvHandle handle)
  1866. {
  1867. _DtCanvasStruct *canvas = (_DtCanvasStruct*)handle;
  1868. (*(canvas->virt_functions.get_metrics))(canvas->client_data,
  1869. _DtCvCANVAS_TYPE, &(canvas->metrics));
  1870. (*(canvas->virt_functions.get_metrics))(canvas->client_data,
  1871. _DtCvLINK_TYPE, &(canvas->link_info));
  1872. (*(canvas->virt_functions.get_metrics))(canvas->client_data,
  1873. _DtCvTRAVERSAL_TYPE, &(canvas->traversal_info));
  1874. if (MB_CUR_MAX > 1)
  1875. (*(canvas->virt_functions.get_metrics))(canvas->client_data,
  1876. _DtCvLOCALE_TYPE, &(canvas->locale));
  1877. }
  1878. /*****************************************************************************
  1879. * Function: void _DtCanvasClean (_DtCvHandle canvas_handle);
  1880. *
  1881. * Parameters:
  1882. * canvas Specifies the handle for the canvas.
  1883. *
  1884. * Returns: A handle to the canvas or NULL if an error occurs.
  1885. *
  1886. * Purpose: Create a canvas and attach the appropriate virtual functions
  1887. * to the canvas.
  1888. *****************************************************************************/
  1889. void
  1890. _DtCanvasClean (_DtCvHandle canvas_handle)
  1891. {
  1892. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  1893. /*
  1894. * clean the selection
  1895. */
  1896. _DtCanvasProcessSelection (canvas_handle, 0, 0, _DtCvSELECTION_CLEAR);
  1897. /*
  1898. * zero the lists
  1899. */
  1900. canvas->txt_cnt = 0;
  1901. canvas->line_cnt = 0;
  1902. canvas->mark_cnt = 0;
  1903. canvas->trav_cnt = 0;
  1904. canvas->search_cnt = 0;
  1905. canvas->brk_cnt = 0;
  1906. /*
  1907. * reset some indicators
  1908. */
  1909. canvas->error = 0;
  1910. canvas->cur_trav = -1;
  1911. /*
  1912. * free the internal use structures.
  1913. */
  1914. _DtCvClearInternalUse(canvas->element_lst, _DtCvTRUE);
  1915. canvas->element_lst = NULL;
  1916. canvas->link_data = NULL;
  1917. } /* End _DtCanvasClean */
  1918. /*****************************************************************************
  1919. * Function: void _DtCanvasDestroy (_DtCvHandle canvas_handle);
  1920. *
  1921. * Parameters:
  1922. * canvas Specifies the handle for the canvas.
  1923. *
  1924. * Returns: A handle to the canvas or NULL if an error occurs.
  1925. *
  1926. * Purpose: Create a canvas and attach the appropriate virtual functions
  1927. * to the canvas.
  1928. *****************************************************************************/
  1929. void
  1930. _DtCanvasDestroy (_DtCvHandle canvas_handle)
  1931. {
  1932. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  1933. _DtCanvasClean (canvas_handle);
  1934. if (NULL != canvas->txt_lst)
  1935. free ((void *) canvas->txt_lst);
  1936. if (NULL != canvas->line_lst)
  1937. free ((void *) canvas->line_lst);
  1938. if (NULL != canvas->trav_lst)
  1939. free ((void *) canvas->trav_lst);
  1940. if (NULL != canvas->marks)
  1941. free ((void*) canvas->marks);
  1942. if (NULL != canvas->searchs)
  1943. free ((void*) canvas->searchs);
  1944. if (NULL != canvas->pg_breaks)
  1945. free ((void*) canvas->pg_breaks);
  1946. free ((void *) canvas);
  1947. return;
  1948. } /* End _DtCanvasDestroy */
  1949. /*****************************************************************************
  1950. * Function: void _DtCanvasRender (_DtCvHandle canvas_handle);
  1951. *
  1952. * Parameters:
  1953. * canvas Specifies the handle for the canvas.
  1954. *
  1955. * Returns: A handle to the canvas or NULL if an error occurs.
  1956. *
  1957. * Purpose:
  1958. *
  1959. *****************************************************************************/
  1960. void
  1961. _DtCanvasRender (
  1962. _DtCvHandle canvas_handle,
  1963. _DtCvUnit x1,
  1964. _DtCvUnit y1,
  1965. _DtCvUnit x2,
  1966. _DtCvUnit y2,
  1967. _DtCvRenderType flag,
  1968. _DtCvValue pg_break,
  1969. _DtCvUnit *max_y,
  1970. _DtCvUnit *next_y)
  1971. {
  1972. int i = 0;
  1973. _DtCvUnit lastY = 0;
  1974. _DtCvUnit nextY = -1;
  1975. _DtCvUnit minY;
  1976. _DtCvUnit maxY;
  1977. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  1978. _DtCvDspLine *lines;
  1979. _DtCvFlags sideCk;
  1980. /*
  1981. * check the list of page breaks, it may constrain y2
  1982. */
  1983. if (_DtCvTRUE == pg_break && 0 != canvas->brk_cnt)
  1984. {
  1985. i = 0;
  1986. while (y1 > canvas->pg_breaks[i]) i++;
  1987. if (i < canvas->brk_cnt && y2 > canvas->pg_breaks[i])
  1988. y2 = canvas->pg_breaks[i];
  1989. }
  1990. /*
  1991. * Draw the lines first, they may constrain y2
  1992. */
  1993. DrawCanvasLines (canvas, x1, y1, x2, y2, flag, &lastY, &nextY);
  1994. if (-1 != nextY && y2 > nextY)
  1995. y2 = nextY - 1;
  1996. /*
  1997. * clear the processed flag from all the text lines.
  1998. */
  1999. for (i = 0; i < canvas->txt_cnt; i++)
  2000. _DtCvClearProcessed(canvas->txt_lst[i]);
  2001. for (lines = canvas->txt_lst, i = 0;
  2002. NULL != lines && i < canvas->txt_cnt; lines++, i++)
  2003. {
  2004. /*
  2005. * get the minimum and maximum y of the next line
  2006. */
  2007. minY = lines->baseline - lines->ascent;
  2008. maxY = lines->baseline + lines->descent;
  2009. /*
  2010. * is this line on the 'page'?
  2011. * Does it hang off the 'page' (and if so is it allowed)?
  2012. */
  2013. sideCk = _DtCvSTATUS_NONE;
  2014. if (_DtCvIsNotProcessed(*lines) && maxY >= y1 && minY <= y2 &&
  2015. (_DtCvRENDER_PARTIAL == flag ||
  2016. (maxY <= y2 &&
  2017. _DtCvTRUE != (sideCk = CheckAround(canvas->txt_lst, canvas->txt_cnt, i, y2)))))
  2018. {
  2019. (void) DrawText (canvas, lines, i, 0, 0);
  2020. /*
  2021. * indicate that this line has been rendered.
  2022. */
  2023. _DtCvSetProcessed(*lines);
  2024. /*
  2025. * if doing complete printing, get any other lines that exist
  2026. * next to this one, but don't fit the [y1,y2] pair. This will
  2027. * catch scrolling problems using _DtCvRENDER_COMPLETE.
  2028. *
  2029. * The previous CheckAround() call will have set sideCk to
  2030. * _DtCvFALSE if there are other items to the side, but these
  2031. * items did not violate the maximum y.
  2032. *
  2033. * sideCk will be _DtCvSTATUS_NONE if there is nothing to the
  2034. * side for _DtCvRENDER_COMPLETE or if flag is _DtCvRENDER_PARTIAL.
  2035. */
  2036. if (_DtCvFALSE == sideCk)
  2037. RenderSubSet(canvas, canvas->txt_lst, canvas->txt_cnt,
  2038. minY, maxY, &lastY);
  2039. /*
  2040. * is this the maximum that we've rendered?
  2041. */
  2042. if (lastY < maxY)
  2043. lastY = maxY;
  2044. }
  2045. /*
  2046. * otherwise, would this 'start' the next 'page'?
  2047. *
  2048. * a) the render type is _DtCvRENDER_PARTIAL but the top of the
  2049. * text(minY) is beyound y2 (and so would maxY).
  2050. * b) the render type is _DtCvRENDER_COMPLETE and the line is
  2051. * split across a page boundary (maxY greater than y2).
  2052. * c) the render type is _DtCvRENDER_COMPLETE and there is text
  2053. * to the side of this text and it is split across a page
  2054. * boundary (sideCk == _DtCvTRUE).
  2055. */
  2056. else if ((-1 == nextY || nextY > minY) &&
  2057. (maxY > y2 || _DtCvTRUE == sideCk))
  2058. nextY = minY;
  2059. }
  2060. /*
  2061. * if doing _DtCvRENDER_PARTIAL, lastY will end up larger than
  2062. * actually rendered. So set it back.
  2063. */
  2064. if (lastY > y2)
  2065. lastY = y2;
  2066. /*
  2067. * return the values if the user asked for them.
  2068. */
  2069. if (NULL != max_y)
  2070. *max_y = lastY;
  2071. if (NULL != next_y)
  2072. *next_y = nextY;
  2073. } /* End _DtCanvasRender */
  2074. /*****************************************************************************
  2075. * Function: void _DtCanvasMoveTraversal ()
  2076. *
  2077. * Parameters:
  2078. * canvas Specifies the handle for the canvas.
  2079. *
  2080. * Returns: A handle to the canvas or NULL if an error occurs.
  2081. *
  2082. * Purpose:
  2083. *
  2084. *****************************************************************************/
  2085. _DtCvStatus
  2086. _DtCanvasMoveTraversal (
  2087. _DtCvHandle canvas_handle,
  2088. _DtCvTraversalCmd cmd,
  2089. _DtCvValue wrap,
  2090. _DtCvValue render,
  2091. _DtCvPointer rid,
  2092. _DtCvUnit *ret_x,
  2093. _DtCvUnit *ret_y,
  2094. _DtCvUnit *ret_baseline,
  2095. _DtCvUnit *ret_height)
  2096. {
  2097. int newIndex;
  2098. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  2099. if (0 == canvas->trav_cnt)
  2100. return _DtCvSTATUS_NONE;
  2101. newIndex = canvas->cur_trav;
  2102. if (-1 == newIndex)
  2103. newIndex = 0;
  2104. switch (cmd)
  2105. {
  2106. case _DtCvTRAVERSAL_TOP:
  2107. newIndex = 0;
  2108. break;
  2109. case _DtCvTRAVERSAL_NEXT:
  2110. newIndex++;
  2111. if (newIndex >= canvas->trav_cnt)
  2112. {
  2113. newIndex--;
  2114. if (wrap == True)
  2115. newIndex = 0;
  2116. }
  2117. break;
  2118. case _DtCvTRAVERSAL_PREV:
  2119. newIndex--;
  2120. if (newIndex < 0)
  2121. {
  2122. newIndex = 0;
  2123. if (wrap == True)
  2124. newIndex = canvas->trav_cnt - 1;
  2125. }
  2126. break;
  2127. case _DtCvTRAVERSAL_BOTTOM:
  2128. newIndex = canvas->trav_cnt - 1;
  2129. break;
  2130. case _DtCvTRAVERSAL_ID:
  2131. case _DtCvTRAVERSAL_MARK:
  2132. if (NULL != rid)
  2133. {
  2134. int idx;
  2135. char *lnkId;
  2136. _DtCvValue found = False;
  2137. newIndex = 0;
  2138. while (False == found && newIndex < canvas->trav_cnt)
  2139. {
  2140. if (_DtCvTRAVERSAL_ID == cmd &&
  2141. _DtCvTraversalLink ==
  2142. canvas->trav_lst[newIndex].type)
  2143. {
  2144. idx = canvas->trav_lst[newIndex].seg_ptr->link_idx;
  2145. lnkId = _DtLinkDbGetLinkSpec(canvas->link_data,
  2146. idx);
  2147. if (_DtCvStrCaseCmpLatin1(lnkId, rid) == 0)
  2148. found = True;
  2149. }
  2150. else if (_DtCvTRAVERSAL_MARK == cmd &&
  2151. _DtCvTraversalMark == canvas->trav_lst[newIndex].type)
  2152. {
  2153. idx = canvas->trav_lst[newIndex].idx;
  2154. if (rid == canvas->marks[idx].client_data)
  2155. found = True;
  2156. }
  2157. if (False == found)
  2158. newIndex++;
  2159. }
  2160. if (False == found)
  2161. return _DtCvSTATUS_BAD;
  2162. }
  2163. break;
  2164. }
  2165. /*
  2166. * turn off the old traversal
  2167. */
  2168. if (cmd == _DtCvTRAVERSAL_OFF)
  2169. {
  2170. if (-1 != canvas->cur_trav)
  2171. DrawTraversalIndicator (canvas, render, False,
  2172. NULL, NULL, NULL, NULL);
  2173. canvas->trav_on = _DtCvFALSE;
  2174. }
  2175. /*
  2176. * turn off the old traversal and turn on the new one.
  2177. */
  2178. else if (newIndex != canvas->cur_trav)
  2179. {
  2180. if (-1 != canvas->cur_trav)
  2181. DrawTraversalIndicator (canvas, render, False,
  2182. NULL, NULL, NULL, NULL);
  2183. canvas->cur_trav = newIndex;
  2184. DrawTraversalIndicator (canvas, render, True,
  2185. ret_x, ret_y, ret_baseline, ret_height);
  2186. canvas->trav_on = _DtCvTRUE;
  2187. return _DtCvSTATUS_OK;
  2188. }
  2189. /*
  2190. * Other wise turn on the traversal
  2191. */
  2192. else if (cmd == _DtCvTRAVERSAL_ON && -1 != canvas->cur_trav)
  2193. {
  2194. DrawTraversalIndicator (canvas, render, True,
  2195. ret_x, ret_y, ret_baseline, ret_height);
  2196. canvas->trav_on = _DtCvTRUE;
  2197. return _DtCvSTATUS_OK;
  2198. }
  2199. return _DtCvSTATUS_NONE;
  2200. }
  2201. /*****************************************************************************
  2202. * Function: void _DtCanvasGetPosLink (_DtCvHandle canvas_handle,
  2203. * _DtCvUnit x, _DtCvUnit y);
  2204. *
  2205. * Parameters:
  2206. * canvas Specifies the handle for the canvas.
  2207. *
  2208. * Returns: A handle to the canvas or NULL if an error occurs.
  2209. *
  2210. * Purpose:
  2211. *
  2212. *****************************************************************************/
  2213. _DtCvStatus
  2214. _DtCanvasGetPosLink (
  2215. _DtCvHandle canvas_handle,
  2216. _DtCvUnit x1,
  2217. _DtCvUnit y1,
  2218. _DtCvUnit x2,
  2219. _DtCvUnit y2,
  2220. _DtCvLinkInfo *ret_info)
  2221. {
  2222. int travIdx;
  2223. int line;
  2224. int len;
  2225. int count;
  2226. int startChar;
  2227. _DtCvUnit topY;
  2228. _DtCvUnit botY;
  2229. _DtCvUnit startX;
  2230. _DtCvUnit endX = 0;
  2231. void *pChar;
  2232. _DtCvValue junk;
  2233. _DtCvStatus found = _DtCvSTATUS_NONE;
  2234. _DtCvSegmentI *pSeg = NULL;
  2235. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  2236. _DtCvTraversalInfo *lnkSegs = canvas->trav_lst;
  2237. if (0 == canvas->trav_cnt)
  2238. return _DtCvSTATUS_NONE;
  2239. botY = 0;
  2240. topY = 0;
  2241. line = 0;
  2242. while (line < canvas->txt_cnt && _DtCvSTATUS_NONE == found)
  2243. {
  2244. topY = canvas->txt_lst[line].baseline - canvas->txt_lst[line].ascent;
  2245. botY = canvas->txt_lst[line].baseline + canvas->txt_lst[line].descent;
  2246. startX = canvas->txt_lst[line].text_x;
  2247. /*
  2248. * make sure the requested link is on this line.
  2249. */
  2250. if (topY <= y1 && y1 <= botY && startX <= x1 &&
  2251. x1 <= canvas->txt_lst[line].max_x)
  2252. {
  2253. int lnkIndx = -1;
  2254. _DtCvValue lstVisible = False;
  2255. count = canvas->txt_lst[line].length;
  2256. pSeg = canvas->txt_lst[line].seg_ptr;
  2257. startChar = canvas->txt_lst[line].byte_index;
  2258. while (count > 0 && _DtCvSTATUS_NONE == found)
  2259. {
  2260. /*
  2261. * adjust the starting position by the link space
  2262. */
  2263. junk = _DtCvIsSegVisibleLink(pSeg);
  2264. lstVisible = _DtCvModifyXpos (canvas->link_info, pSeg,
  2265. junk, lstVisible, lnkIndx, &startX);
  2266. /*
  2267. * adjust the starting position by the traversal space
  2268. */
  2269. junk = _DtCvIsSegALink(pSeg);
  2270. (void) _DtCvModifyXpos (canvas->traversal_info, pSeg,
  2271. junk, ((_DtCvValue) True), lnkIndx, &startX);
  2272. lnkIndx = pSeg->link_idx;
  2273. /*
  2274. * skip no-op
  2275. */
  2276. if (_DtCvIsSegNoop(pSeg))
  2277. len = 0;
  2278. /*
  2279. * check region
  2280. */
  2281. else if (_DtCvIsSegRegion(pSeg))
  2282. {
  2283. len = 1;
  2284. endX = startX + _DtCvWidthOfRegionSeg(pSeg);
  2285. }
  2286. else
  2287. {
  2288. /*
  2289. * initialize the pointer to the string
  2290. */
  2291. pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
  2292. _DtCvIsSegWideChar(pSeg), startChar);
  2293. /*
  2294. * get the length of the current string.
  2295. * If it is longer than the line count indicates,
  2296. * it must be wrapped to the next line. We are
  2297. * only interested in in the part of the line
  2298. * that is on the line selected.
  2299. */
  2300. len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(pSeg));
  2301. if (len > count)
  2302. len = count;
  2303. /*
  2304. * calculate the ending pixel postion for
  2305. * this string segment.
  2306. */
  2307. endX = startX + _DtCvGetStringWidth(canvas, pSeg,
  2308. pChar, len);
  2309. }
  2310. /*
  2311. * test to see if the selected segment was this segment.
  2312. */
  2313. if (x1 >= startX && x1 < endX && x2 >= startX && x2 < endX)
  2314. {
  2315. found = _DtCvSTATUS_OK;
  2316. /*
  2317. * Find the hypertext entry.
  2318. */
  2319. travIdx = 0;
  2320. while (travIdx < canvas->trav_cnt
  2321. && _DtCvTraversalLink == lnkSegs->type
  2322. && lnkSegs->seg_ptr->link_idx != pSeg->link_idx)
  2323. {
  2324. lnkSegs++;
  2325. travIdx++;
  2326. }
  2327. }
  2328. else
  2329. {
  2330. /*
  2331. * go to the next segment.
  2332. */
  2333. pSeg = pSeg->next_disp;
  2334. /*
  2335. * adjust for the new begining.
  2336. */
  2337. startX = endX;
  2338. count = count - len;
  2339. startChar = 0;
  2340. }
  2341. }
  2342. }
  2343. line++;
  2344. }
  2345. /*
  2346. * check to see if we found a segment and
  2347. * see if it is a hypertext segment
  2348. */
  2349. if (_DtCvSTATUS_OK == found)
  2350. {
  2351. found = _DtCvSTATUS_NONE;
  2352. if (_DtCvIsSegALink(pSeg) &&
  2353. _DtLinkDbGetLinkInfo(canvas->link_data, pSeg->link_idx,
  2354. canvas->virt_functions.exec_cmd_filter,
  2355. canvas->client_data, ret_info) == 0)
  2356. {
  2357. ret_info->offset_x = x1 - startX;
  2358. ret_info->offset_y = y1 - topY;
  2359. found = _DtCvSTATUS_OK;
  2360. }
  2361. }
  2362. return found;
  2363. } /* End _DtCanvasGetPosLink */
  2364. /*****************************************************************************
  2365. * Function: void _DtCanvasGetCurLink ()
  2366. *
  2367. * Parameters:
  2368. * canvas Specifies the handle for the canvas.
  2369. *
  2370. * Returns: A handle to the canvas or NULL if an error occurs.
  2371. *
  2372. * Purpose:
  2373. *
  2374. *****************************************************************************/
  2375. _DtCvStatus
  2376. _DtCanvasGetCurLink (
  2377. _DtCvHandle canvas_handle,
  2378. _DtCvLinkInfo *ret_info)
  2379. {
  2380. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  2381. _DtCvSegmentI *pSeg;
  2382. int curTrav = canvas->cur_trav;
  2383. /*
  2384. * if there isn't any traversal entry or it is a mark, return nothing.
  2385. */
  2386. if (0 == canvas->trav_cnt || -1 == curTrav ||
  2387. _DtCvTraversalMark == canvas->trav_lst[curTrav].type)
  2388. return _DtCvSTATUS_NONE;
  2389. /*
  2390. * otherwise this is a hypertext link
  2391. */
  2392. if (NULL != ret_info &&
  2393. _DtCvTraversalLink == canvas->trav_lst[curTrav].type)
  2394. {
  2395. pSeg = canvas->trav_lst[curTrav].seg_ptr;
  2396. if (_DtLinkDbGetLinkInfo(canvas->link_data, pSeg->link_idx,
  2397. canvas->virt_functions.exec_cmd_filter,
  2398. canvas->client_data, ret_info) == 0)
  2399. return _DtCvSTATUS_OK;
  2400. }
  2401. return _DtCvSTATUS_BAD;
  2402. }
  2403. /*****************************************************************************
  2404. * Function: void _DtCanvasGetCurTraversal ()
  2405. *
  2406. * Parameters:
  2407. * canvas Specifies the handle for the canvas.
  2408. *
  2409. * Returns: A handle to the canvas or NULL if an error occurs.
  2410. *
  2411. * Purpose:
  2412. *
  2413. *****************************************************************************/
  2414. _DtCvStatus
  2415. _DtCanvasGetCurTraversal (
  2416. _DtCvHandle canvas_handle,
  2417. _DtCvLinkInfo *ret_info,
  2418. _DtCvPointer *ret_data)
  2419. {
  2420. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  2421. _DtCvSegmentI *pSeg;
  2422. int curTrav = canvas->cur_trav;
  2423. /*
  2424. * if there isn't any traversal entry, return nothing.
  2425. */
  2426. if (0 == canvas->trav_cnt || -1 == curTrav)
  2427. return _DtCvSTATUS_NONE;
  2428. /*
  2429. * if this is a mark, return the client data.
  2430. */
  2431. if (NULL != ret_data &&
  2432. _DtCvTraversalMark == canvas->trav_lst[curTrav].type)
  2433. {
  2434. *ret_data = canvas->marks[canvas->trav_lst[curTrav].idx].client_data;
  2435. return _DtCvSTATUS_MARK;
  2436. }
  2437. /*
  2438. * otherwise this is a hypertext link
  2439. */
  2440. if (NULL != ret_info &&
  2441. _DtCvTraversalLink == canvas->trav_lst[curTrav].type)
  2442. {
  2443. pSeg = canvas->trav_lst[curTrav].seg_ptr;
  2444. if (_DtLinkDbGetLinkInfo(canvas->link_data, pSeg->link_idx,
  2445. canvas->virt_functions.exec_cmd_filter,
  2446. canvas->client_data, ret_info) == 0)
  2447. return _DtCvSTATUS_LINK;
  2448. }
  2449. return _DtCvSTATUS_BAD;
  2450. }
  2451. /*****************************************************************************
  2452. * Function: void _DtCanvasGetSpotInfo (_DtCvHandle canvas_handle,
  2453. * _DtCvUnit x, _DtCvUnit y);
  2454. *
  2455. * Parameters:
  2456. * canvas Specifies the handle for the canvas.
  2457. *
  2458. * Returns: _DtCvSTATUS_OK if a segment was found at x, y.
  2459. * _DtCvSTATUS_NONE if no segment found at that location.
  2460. *
  2461. * Purpose:
  2462. *
  2463. *****************************************************************************/
  2464. _DtCvStatus
  2465. _DtCanvasGetSpotInfo (
  2466. _DtCvHandle canvas_handle,
  2467. _DtCvUnit x,
  2468. _DtCvUnit y,
  2469. _DtCvSegment **ret_seg,
  2470. _DtCvUnit *ret_offx,
  2471. _DtCvUnit *ret_offy,
  2472. _DtCvElemType *ret_elem)
  2473. {
  2474. int line;
  2475. int len;
  2476. int count;
  2477. int startChar;
  2478. _DtCvUnit topY;
  2479. _DtCvUnit botY;
  2480. _DtCvUnit startX;
  2481. _DtCvUnit endX = 0;
  2482. void *pChar;
  2483. _DtCvValue junk;
  2484. _DtCvStatus found = _DtCvSTATUS_NONE;
  2485. _DtCvSegmentI *pSeg = NULL;
  2486. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  2487. if (NULL != ret_seg)
  2488. *ret_seg = NULL;
  2489. botY = 0;
  2490. topY = 0;
  2491. line = 0;
  2492. while (line < canvas->txt_cnt && _DtCvSTATUS_NONE == found)
  2493. {
  2494. topY = canvas->txt_lst[line].baseline - canvas->txt_lst[line].ascent;
  2495. botY = canvas->txt_lst[line].baseline + canvas->txt_lst[line].descent;
  2496. startX = canvas->txt_lst[line].text_x;
  2497. /*
  2498. * make sure the requested link is on this line.
  2499. */
  2500. if (topY <= y && y <= botY && startX <= x &&
  2501. x <= canvas->txt_lst[line].max_x)
  2502. {
  2503. int lnkIndx = -1;
  2504. _DtCvValue lstVisible = False;
  2505. count = canvas->txt_lst[line].length;
  2506. pSeg = canvas->txt_lst[line].seg_ptr;
  2507. startChar = canvas->txt_lst[line].byte_index;
  2508. while (count > 0 && _DtCvSTATUS_NONE == found)
  2509. {
  2510. /*
  2511. * adjust the starting position by the link space
  2512. */
  2513. junk = _DtCvIsSegVisibleLink(pSeg);
  2514. lstVisible = _DtCvModifyXpos (canvas->link_info, pSeg,
  2515. junk, lstVisible, lnkIndx, &startX);
  2516. /*
  2517. * adjust the starting position by the traversal space
  2518. */
  2519. junk = _DtCvIsSegALink(pSeg);
  2520. (void) _DtCvModifyXpos (canvas->traversal_info, pSeg,
  2521. junk, ((_DtCvValue) True), lnkIndx, &startX);
  2522. lnkIndx = pSeg->link_idx;
  2523. /*
  2524. * skip no-op
  2525. */
  2526. if (_DtCvIsSegNoop(pSeg))
  2527. len = 0;
  2528. /*
  2529. * check region
  2530. */
  2531. else if (_DtCvIsSegRegion(pSeg))
  2532. {
  2533. len = 1;
  2534. endX = startX + _DtCvWidthOfRegionSeg(pSeg);
  2535. }
  2536. else
  2537. {
  2538. /*
  2539. * initialize the pointer to the string
  2540. */
  2541. pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
  2542. _DtCvIsSegWideChar(pSeg), startChar);
  2543. /*
  2544. * get the length of the current string.
  2545. * If it is longer than the line count indicates,
  2546. * it must be wrapped to the next line. We are
  2547. * only interested in in the part of the line
  2548. * that is on the line selected.
  2549. */
  2550. len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(pSeg));
  2551. if (len > count)
  2552. len = count;
  2553. /*
  2554. * calculate the ending pixel postion for
  2555. * this string segment.
  2556. */
  2557. endX = startX + _DtCvGetStringWidth(canvas, pSeg,
  2558. pChar, len);
  2559. }
  2560. /*
  2561. * test to see if the selected segment was this segment.
  2562. */
  2563. if (x >= startX && x < endX)
  2564. found = _DtCvSTATUS_OK;
  2565. else
  2566. {
  2567. /*
  2568. * go to the next segment.
  2569. */
  2570. pSeg = pSeg->next_disp;
  2571. /*
  2572. * adjust for the new begining.
  2573. */
  2574. startX = endX;
  2575. count = count - len;
  2576. startChar = 0;
  2577. }
  2578. }
  2579. }
  2580. line++;
  2581. }
  2582. /*
  2583. * check to see if we found a segment.
  2584. */
  2585. if (_DtCvSTATUS_OK == found)
  2586. {
  2587. *ret_elem = _DtCvREGION_TYPE;
  2588. if (_DtCvIsSegString(pSeg))
  2589. *ret_elem = _DtCvSTRING_TYPE;
  2590. if (NULL != ret_seg)
  2591. *ret_seg = pSeg;
  2592. if (NULL != ret_offx)
  2593. *ret_offx = x - startX;
  2594. if (NULL != ret_offy)
  2595. *ret_offy = y - topY;
  2596. }
  2597. return found;
  2598. } /* End _DtCanvasGetPosition */