Selection.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729
  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. /* $XConsortium: Selection.c /main/22 1996/11/12 11:44:48 cde-hp $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: Selection.c
  28. **
  29. ** Project: Cde DtHelp
  30. **
  31. ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
  32. **
  33. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  34. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  35. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  36. ** (c) Copyright 1993, 1994 Novell, Inc.
  37. **
  38. **
  39. ****************************************************************************
  40. ************************************<+>*************************************/
  41. /*
  42. * system includes
  43. */
  44. #include <stdlib.h>
  45. #include <string.h>
  46. /*
  47. * Canvas Engine includes
  48. */
  49. #include "CanvasP.h"
  50. #include "CanvasSegP.h"
  51. /*
  52. * private includes
  53. */
  54. #include "CanvasI.h"
  55. #include "CvStringI.h"
  56. #include "LayoutUtilI.h"
  57. #include "SelectionI.h"
  58. #include "VirtFuncsI.h"
  59. #ifdef NLS16
  60. #endif
  61. /******** Private Function Declarations ********/
  62. static void AdjustSelection (
  63. _DtCanvasStruct *canvas,
  64. _DtCvSelectData next);
  65. static int GetSelectedText(
  66. _DtCanvasStruct *canvas,
  67. _DtCvSelectData start,
  68. _DtCvSelectData end,
  69. unsigned int mask,
  70. _DtCvPointer *ret_data);
  71. /******** End Private Function Declarations ********/
  72. /******** Private Defines ********/
  73. #define GROW_SIZE 5
  74. /******** End Private Defines ********/
  75. /******** Macros ********/
  76. #define Equal(a,b) (a.y == b.y && a.x == b.x)
  77. #define LessThan(a,b) ((a.y < b.y) || (a.y == b.y && a.x < b.x))
  78. #define GreaterThan(a,b) ((a.y > b.y) || (a.y == b.y && a.x > b.x))
  79. #define LessThanEq(a,b) (Equal(a,b) || LessThan(a,b))
  80. #define GreaterThanEq(a,b) (Equal(a,b) || GreaterThan(a,b))
  81. #define InRegion(top,bot,min,max) ((min) <= (bot) && (top) <= (max))
  82. /******** End Macros ********/
  83. /******** Private Variable Declarations ********/
  84. static const _DtCvSelectData defaultSelect = { -1, -1, -1, -1};
  85. /******** End Private Variable Declarations ********/
  86. /******************************************************************************
  87. * Private Functions
  88. ******************************************************************************/
  89. /******************************************************************************
  90. * Function: StartXOfLine
  91. *
  92. * Purpose: Determine the start of a line, takes into consideration
  93. * the traversal and link before values. The 'x' returned is
  94. * exactly where the text/graphic is to be placed on the canvas.
  95. *****************************************************************************/
  96. static _DtCvUnit
  97. StartXOfLine(
  98. _DtCanvasStruct *canvas,
  99. _DtCvDspLine line)
  100. {
  101. _DtCvValue lastLinkVisible = FALSE;
  102. int lnkInd = -1;
  103. _DtCvUnit xPos;
  104. _DtCvSegmentI *pSeg;
  105. xPos = _DtCvGetStartXOfLine(&line, &pSeg);
  106. return (_DtCvAdvanceXOfLine( canvas, pSeg, xPos,
  107. &lnkInd, &lastLinkVisible));
  108. } /* End StartXOfLine */
  109. /*****************************************************************************
  110. * Function: SearchForClosestLine
  111. *
  112. * Purpose: Initializes the 'new' structure with information indicating
  113. * what line is closest to the target_y.
  114. * next->y Set to target_y if no line straddles it.
  115. * Otherwise, it will be set to the minimum
  116. * y of all lines straddling the target_y.
  117. * next->x Set to target_x if no line straddles
  118. * target_y or if target_x is before the
  119. * first line straddling target_y.
  120. * next->line_idx Set to -1 if no line straddles target_y.
  121. * Otherwise, set to the first line that
  122. * straddles target_x or is the minimum x
  123. * that is greater than target_x of all the
  124. * lines straddling target_x.
  125. * next->char_idx Set to -1 if no straddles target_y.
  126. * Otherwise, set to the character that
  127. * resides at target_x if target_x is in
  128. * the middle of the line. Set to zero if
  129. * target_x is before the line, and set to
  130. * the line count if target_x is after the
  131. * line.
  132. *
  133. *****************************************************************************/
  134. static void
  135. SearchForClosestLine (
  136. _DtCanvasStruct *canvas,
  137. _DtCvUnit target_x,
  138. _DtCvUnit target_y,
  139. _DtCvSelectData *next)
  140. {
  141. int i;
  142. int maxI = 0;
  143. _DtCvUnit lineY;
  144. _DtCvUnit endX;
  145. _DtCvUnit begX;
  146. _DtCvUnit maxX = -1;
  147. _DtCvDspLine *lines = canvas->txt_lst;
  148. *next = defaultSelect;
  149. for (i = 0; i < canvas->txt_cnt; i++)
  150. {
  151. /*
  152. * get the maximum y of the line
  153. * if it straddles the target y, process it.
  154. */
  155. lineY = lines[i].baseline + lines[i].descent;
  156. if (_DtCvStraddlesPt(target_y,lines[i].baseline-lines[i].ascent,lineY))
  157. {
  158. /*
  159. * Is this the minimum y of all the maximum y values of the
  160. * line straddling the target y?
  161. */
  162. if (next->y == -1 || next->y > lineY)
  163. next->y = lineY;
  164. /*
  165. * Get the maximum X position of the line.
  166. * If this is the maximum X of all the lines straddling
  167. * the target y, remember it.
  168. */
  169. endX = canvas->txt_lst[i].max_x;
  170. if (maxX < endX && endX < target_x)
  171. {
  172. maxX = endX;
  173. maxI = i;
  174. }
  175. /*
  176. * Does this line straddle the x?
  177. */
  178. begX = StartXOfLine(canvas, lines[i]);
  179. if (_DtCvStraddlesPt(target_x, begX, endX))
  180. {
  181. next->line_idx = i;
  182. next->char_idx = _DtCvGetCharIdx(canvas,lines[i],target_x);
  183. }
  184. }
  185. }
  186. /*
  187. * remember what the target x was for this line. If the target x is
  188. * less than the start of the line, then the selection process will
  189. * highlight the space before the line. If its in the middle, it
  190. * will just highlight starting at the character. If it's after the
  191. * end, the rest will be cut off at the end of the line.
  192. */
  193. next->x = target_x;
  194. /*
  195. * If we found a line straddling the target y, but it does not
  196. * straddle the target_x, check max x for the correct info.
  197. */
  198. if (next->line_idx == -1 && maxX > -1)
  199. {
  200. next->line_idx = maxI;
  201. next->char_idx = lines[maxI].length;
  202. }
  203. /*
  204. * didn't find a line straddling the target_y, set y.
  205. */
  206. if (next->y == -1)
  207. next->y = target_y;
  208. }
  209. /*****************************************************************************
  210. * Function: MarkLinesOutsideBoundary
  211. *
  212. *****************************************************************************/
  213. static void
  214. MarkLinesOutsideBoundary (
  215. _DtCanvasStruct *canvas,
  216. _DtCvUnit top_y,
  217. _DtCvUnit top_x,
  218. _DtCvUnit bot_y,
  219. _DtCvUnit bot_x)
  220. {
  221. int i;
  222. _DtCvUnit maxY;
  223. _DtCvUnit minY;
  224. _DtCvDspLine *lines = canvas->txt_lst;
  225. for (i = 0; i < canvas->txt_cnt; i++)
  226. {
  227. maxY = lines[i].baseline + lines[i].descent;
  228. minY = lines[i].baseline - lines[i].ascent;
  229. /*
  230. * is this line outside the boundary?
  231. * If so, mark it so it's not processed.
  232. */
  233. if (maxY < top_y || minY > bot_y )
  234. _DtCvSetProcessed(lines[i]);
  235. else
  236. {
  237. /*
  238. * does it straddle the top?
  239. */
  240. if (_DtCvStraddlesPt(top_y, minY, maxY))
  241. {
  242. /*
  243. * Does it begin before the selection?
  244. * If so, mark it so it's not processed.
  245. */
  246. if (canvas->txt_lst[i].max_x <= top_x)
  247. _DtCvSetProcessed(lines[i]);
  248. }
  249. /*
  250. * does it straddle the bottom?
  251. */
  252. if (_DtCvStraddlesPt(bot_y, minY, maxY))
  253. {
  254. /*
  255. * Does it start after the selection?
  256. * If so, mark it so it's not processed.
  257. */
  258. if (StartXOfLine(canvas, lines[i]) >= bot_x)
  259. _DtCvSetProcessed(lines[i]);
  260. }
  261. }
  262. }
  263. }
  264. /*****************************************************************************
  265. * Function: AdjustSelection
  266. *
  267. *****************************************************************************/
  268. static void
  269. AdjustSelection (
  270. _DtCanvasStruct *canvas,
  271. _DtCvSelectData next)
  272. {
  273. _DtCvSelectData start = canvas->select_start;
  274. _DtCvSelectData end = canvas->select_end;
  275. if (!(Equal(next, end)))
  276. {
  277. if (next.line_idx != -1 && next.line_idx == canvas->select_end.line_idx
  278. &&
  279. next.char_idx != -1 && next.char_idx == canvas->select_end.char_idx)
  280. return;
  281. if (GreaterThan(next, end))
  282. {
  283. if (LessThanEq(start, end))
  284. _DtCvDrawAreaWithFlags (canvas, end, next,
  285. 0, _DtCvSELECTED_FLAG,
  286. _DtCvBAD_TYPE, NULL);
  287. else if (GreaterThanEq(start, next))
  288. _DtCvDrawAreaWithFlags (canvas, end, next,
  289. _DtCvSELECTED_FLAG, 0,
  290. _DtCvBAD_TYPE, NULL);
  291. else /* end < start < next */
  292. {
  293. _DtCvDrawAreaWithFlags (canvas, end , start,
  294. _DtCvSELECTED_FLAG, 0,
  295. _DtCvBAD_TYPE, NULL);
  296. _DtCvDrawAreaWithFlags (canvas, start, next ,
  297. 0, _DtCvSELECTED_FLAG,
  298. _DtCvBAD_TYPE, NULL);
  299. }
  300. }
  301. else /* if (next < end) */
  302. {
  303. if (LessThanEq(start, next))
  304. _DtCvDrawAreaWithFlags (canvas, next, end,
  305. _DtCvSELECTED_FLAG, 0,
  306. _DtCvBAD_TYPE, NULL);
  307. else if (GreaterThanEq(start, end))
  308. _DtCvDrawAreaWithFlags (canvas, next, end,
  309. 0, _DtCvSELECTED_FLAG,
  310. _DtCvBAD_TYPE, NULL);
  311. else /* next < start < end */
  312. {
  313. _DtCvDrawAreaWithFlags (canvas, start, end ,
  314. _DtCvSELECTED_FLAG, 0,
  315. _DtCvBAD_TYPE, NULL);
  316. _DtCvDrawAreaWithFlags (canvas, next , start,
  317. 0, _DtCvSELECTED_FLAG,
  318. _DtCvBAD_TYPE, NULL);
  319. }
  320. }
  321. }
  322. canvas->select_end = next;
  323. }
  324. /*****************************************************************************
  325. * Function: SkipOtherLines
  326. *
  327. *****************************************************************************/
  328. static void
  329. SkipOtherLines(
  330. _DtCvDspLine *lines,
  331. int max_cnt,
  332. int idx,
  333. _DtCvUnit target_y,
  334. int *ret_idx)
  335. {
  336. while (idx < max_cnt && _DtCvIsNotProcessed(lines[idx]) &&
  337. lines[idx].baseline - lines[idx].ascent > target_y)
  338. idx++;
  339. *ret_idx = idx;
  340. }
  341. /*****************************************************************************
  342. * Function: CheckAndSwitchPoints
  343. *
  344. *****************************************************************************/
  345. static int
  346. CheckAndSwitchPoints(
  347. _DtCvSelectData *pt1,
  348. _DtCvSelectData *pt2)
  349. {
  350. _DtCvSelectData temp;
  351. if (pt1->y > pt2->y || (pt1->y == pt2->y && pt1->x > pt2->x))
  352. {
  353. temp = *pt2;
  354. *pt2 = *pt1;
  355. *pt1 = temp;
  356. }
  357. }
  358. /*****************************************************************************
  359. * Function: AddSegmentToData
  360. *
  361. *****************************************************************************/
  362. static _DtCvUnit
  363. AddSegmentToData(
  364. _DtCanvasStruct *canvas,
  365. unsigned int mask,
  366. _DtCvUnit start_x,
  367. int line_idx,
  368. int char_idx,
  369. int copy_cnt,
  370. _DtCvFlags end_flag,
  371. _DtCvUnit *ret_y,
  372. _DtCvPointer *ret_data)
  373. {
  374. _DtCvDspLine line = canvas->txt_lst[line_idx];
  375. int result = _DtCvSTATUS_OK;
  376. int count = line.length;
  377. int start = line.byte_index;
  378. int lnkInd = -1;
  379. int cnt;
  380. int len;
  381. _DtCvUnit segWidth;
  382. _DtCvUnit xPos = line.text_x;
  383. void *pChar;
  384. _DtCvSegmentI *pSeg = line.seg_ptr;
  385. _DtCvFlags flag = 0;
  386. _DtCvValue done = False;
  387. _DtCvValue lastLinkVisible = FALSE;
  388. _DtCvStringInfo strInfo;
  389. xPos = _DtCvGetStartXOfLine(&line, &pSeg);
  390. while (done == False && char_idx)
  391. {
  392. /*
  393. * advance past the link and traversal info
  394. */
  395. xPos = _DtCvAdvanceXOfLine(canvas, pSeg, xPos,
  396. &lnkInd, &lastLinkVisible);
  397. /*
  398. * advance the pointer by the width
  399. */
  400. _DtCvGetWidthOfSegment(canvas, pSeg, start, count,
  401. &cnt, &segWidth, NULL);
  402. if (cnt < char_idx)
  403. {
  404. xPos += segWidth;
  405. pSeg = pSeg->next_disp;
  406. count -= cnt;
  407. char_idx -= cnt;
  408. start = 0;
  409. }
  410. else
  411. {
  412. _DtCvGetWidthOfSegment(canvas, pSeg, start, char_idx,
  413. &cnt, &segWidth, NULL);
  414. xPos += segWidth;
  415. start += cnt;
  416. count -= cnt;
  417. done = True;
  418. }
  419. }
  420. if (start_x > xPos)
  421. start_x = xPos;
  422. while (_DtCvSTATUS_OK == result && pSeg != NULL && copy_cnt > 0)
  423. {
  424. /*
  425. * advance past the link and traversal info
  426. */
  427. xPos = _DtCvAdvanceXOfLine(canvas, pSeg, xPos,
  428. &lnkInd, &lastLinkVisible);
  429. switch (_DtCvPrimaryTypeOfSeg(pSeg))
  430. {
  431. case _DtCvSTRING:
  432. pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
  433. _DtCvIsSegWideChar(pSeg), start);
  434. len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(pSeg));
  435. if (len > copy_cnt)
  436. len = copy_cnt;
  437. segWidth = _DtCvGetStringWidth(canvas, pSeg, pChar, len);
  438. if (copy_cnt == len)
  439. flag = end_flag;
  440. strInfo.string = pChar;
  441. strInfo.byte_len = len;
  442. strInfo.wc = _DtCvIsSegWideChar(pSeg);
  443. strInfo.font_ptr = _DtCvFontOfStringSeg(pSeg);
  444. if (canvas->virt_functions.build_selection != NULL)
  445. result = (*(canvas->virt_functions.build_selection))(
  446. canvas->client_data,
  447. _DtCvSTRING_TYPE,
  448. mask,
  449. ret_data,
  450. xPos - start_x,
  451. segWidth,
  452. flag,
  453. (_DtCvPointer) &strInfo);
  454. if (_DtCvSTATUS_OK == result)
  455. {
  456. if (line.baseline + line.descent > *ret_y)
  457. *ret_y = line.baseline + line.descent;
  458. start_x = xPos + segWidth;
  459. }
  460. else if (_DtCvSTATUS_NONE == result)
  461. result = _DtCvSTATUS_OK;
  462. xPos += segWidth;
  463. copy_cnt -= len;
  464. start = 0;
  465. break;
  466. case _DtCvREGION:
  467. if (copy_cnt == 1)
  468. flag = end_flag;
  469. if (canvas->virt_functions.build_selection != NULL)
  470. result = (*(canvas->virt_functions.build_selection))(
  471. canvas->client_data,
  472. _DtCvREGION_TYPE,
  473. mask,
  474. ret_data,
  475. xPos - start_x,
  476. _DtCvWidthOfRegionSeg(pSeg),
  477. flag,
  478. _DtCvInfoOfRegionSeg(pSeg));
  479. if (_DtCvSTATUS_OK == result)
  480. {
  481. if (line.baseline + line.descent > *ret_y)
  482. *ret_y = line.baseline + line.descent;
  483. start_x = xPos + segWidth;
  484. }
  485. else if (_DtCvSTATUS_NONE == result)
  486. result = _DtCvSTATUS_OK;
  487. copy_cnt--;
  488. xPos += _DtCvWidthOfRegionSeg(pSeg);
  489. break;
  490. }
  491. pSeg = pSeg->next_disp;
  492. }
  493. if (result != _DtCvSTATUS_OK)
  494. return -1;
  495. return start_x;
  496. }
  497. /*****************************************************************************
  498. * Function: BuildLine
  499. *
  500. *****************************************************************************/
  501. static int
  502. BuildLine(
  503. _DtCanvasStruct *canvas,
  504. unsigned int mask,
  505. _DtCvUnit prev_y,
  506. _DtCvUnit target_x,
  507. int line_idx,
  508. int char_idx,
  509. int copy_cnt,
  510. _DtCvFlags end_flag,
  511. _DtCvUnit *ret_x,
  512. _DtCvUnit *ret_y,
  513. _DtCvPointer *ret_data)
  514. {
  515. _DtCvUnit topY;
  516. _DtCvDspLine *lines = canvas->txt_lst;
  517. _DtCvStringInfo strInfo = { NULL, 0, 1, NULL };
  518. topY = lines[line_idx].baseline - lines[line_idx].ascent;
  519. if (topY > prev_y && canvas->virt_functions.build_selection != NULL)
  520. {
  521. int newLines;
  522. _DtCvUnit lineSize = canvas->metrics.line_height / 2;
  523. if (lineSize < 1)
  524. lineSize = 1;
  525. newLines = (topY - prev_y) / lineSize;
  526. while (newLines > 0)
  527. {
  528. newLines--;
  529. if ((*(canvas->virt_functions.build_selection))(
  530. canvas->client_data, _DtCvSTRING_TYPE,
  531. mask, ret_data, 0, 0, _DtCvEND_OF_LINE,
  532. (_DtCvPointer) &strInfo) != _DtCvSTATUS_OK)
  533. return -1;
  534. }
  535. }
  536. *ret_y = 0;
  537. *ret_x = AddSegmentToData (canvas, mask, target_x, line_idx, char_idx,
  538. copy_cnt, end_flag, ret_y, ret_data);
  539. _DtCvSetProcessed(lines[line_idx]);
  540. if (*ret_x == -1)
  541. return -1;
  542. return 0;
  543. }
  544. /*****************************************************************************
  545. * Function: FindMinX
  546. *
  547. *****************************************************************************/
  548. static int
  549. FindMinX (
  550. _DtCvDspLine *lines,
  551. int txt_cnt,
  552. _DtCvUnit target_y,
  553. int *ret_line)
  554. {
  555. int i;
  556. int cnt = 0;
  557. _DtCvUnit curMin = -1;
  558. _DtCvUnit curX;
  559. for (i = 0; i < txt_cnt; i++)
  560. {
  561. if (_DtCvIsNotProcessed(lines[i]))
  562. {
  563. if (lines[i].baseline - lines[i].ascent < target_y &&
  564. target_y <= lines[i].baseline + lines[i].descent)
  565. {
  566. cnt++;
  567. curX = lines[i].text_x;
  568. if (curMin == -1 || curMin > curX)
  569. {
  570. curMin = curX;
  571. *ret_line = i;
  572. }
  573. }
  574. }
  575. }
  576. return cnt;
  577. }
  578. /*****************************************************************************
  579. * Function: FindNextMinY
  580. *
  581. *****************************************************************************/
  582. static _DtCvValue
  583. FindNextMinY(
  584. _DtCvDspLine *lines,
  585. int max_cnt,
  586. _DtCvUnit target_y,
  587. _DtCvUnit *ret_y)
  588. {
  589. int i = 0;
  590. _DtCvUnit maxY;
  591. _DtCvValue found = False;
  592. while (i < max_cnt)
  593. {
  594. if (_DtCvIsNotProcessed(lines[i]))
  595. {
  596. maxY = lines[i].baseline + lines[i].descent;
  597. if (target_y == -1 || maxY < target_y)
  598. {
  599. found = True;
  600. target_y = maxY;
  601. }
  602. SkipOtherLines (lines, max_cnt, i+1, target_y, &i);
  603. }
  604. else
  605. i++;
  606. }
  607. *ret_y = target_y;
  608. return found;
  609. }
  610. /*****************************************************************************
  611. * Function: GetSelectedText
  612. *
  613. *****************************************************************************/
  614. static int
  615. GetSelectedText(
  616. _DtCanvasStruct *canvas,
  617. _DtCvSelectData next,
  618. _DtCvSelectData end,
  619. unsigned int mask,
  620. _DtCvPointer *ret_data)
  621. {
  622. _DtCvUnit maxY;
  623. _DtCvUnit botY;
  624. int i;
  625. int lineCnt = 0;
  626. int junk;
  627. int result = 0;
  628. int cpyCnt = 0;
  629. int txtCnt = canvas->txt_cnt;
  630. _DtCvFlags endFlag;
  631. _DtCvValue processing = True;
  632. _DtCvDspLine *lines = canvas->txt_lst;
  633. for (i = 0; i < txtCnt; i++)
  634. _DtCvClearProcessed(lines[i]);
  635. MarkLinesOutsideBoundary(canvas, next.y, next.x, end.y, end.x);
  636. maxY = next.y;
  637. if (next.line_idx == -1)
  638. {
  639. /*
  640. * find the first selected line
  641. */
  642. if (FindNextMinY(lines, txtCnt, -1, &next.y) == False)
  643. return 0;
  644. next.x = 0;
  645. lineCnt = FindMinX(lines, txtCnt, next.y, &next.line_idx);
  646. next.char_idx = 0;
  647. }
  648. else
  649. lineCnt = FindMinX(lines, txtCnt, next.y, &junk);
  650. while (processing == True && result == 0)
  651. {
  652. /*
  653. * process the next line of text.
  654. */
  655. do
  656. {
  657. endFlag = 0;
  658. cpyCnt = lines[next.line_idx].length - next.char_idx;
  659. if (next.line_idx == end.line_idx)
  660. cpyCnt = cpyCnt - lines[next.line_idx].length + end.char_idx;
  661. else if (lineCnt == 1)
  662. endFlag = _DtCvEND_OF_LINE;
  663. result = BuildLine(canvas, mask, maxY, next.x,
  664. next.line_idx, next.char_idx,
  665. cpyCnt, endFlag,
  666. &next.x, &botY, ret_data);
  667. if (botY > maxY)
  668. maxY = botY;
  669. next.char_idx = 0;
  670. lineCnt = FindMinX(lines, txtCnt, next.y, &next.line_idx);
  671. } while (result == 0 && lineCnt > 0);
  672. if (result == 0)
  673. {
  674. next.x = 0;
  675. processing = FindNextMinY(lines, txtCnt, -1, &next.y);
  676. if (processing == True)
  677. lineCnt = FindMinX(lines, txtCnt, next.y, &next.line_idx);
  678. }
  679. }
  680. return result;
  681. } /* End GetSelectedText */
  682. /*****************************************************************************
  683. * Function: GetSegsInArea()
  684. *
  685. * Purpose: Retrieve the segments making up the selection.
  686. *
  687. *****************************************************************************/
  688. static _DtCvStatus
  689. GetSegsInArea (
  690. _DtCanvasStruct *canvas,
  691. _DtCvSelectData *beg,
  692. _DtCvSelectData *end,
  693. _DtCvSegPts ***ret_segs,
  694. _DtCvUnit *ret_y1,
  695. _DtCvUnit *ret_y2)
  696. {
  697. int cnt;
  698. int count;
  699. int start;
  700. int length;
  701. int lineCnt;
  702. int result = 0;
  703. _DtCvValue processing = True;
  704. _DtCvUnit minY;
  705. _DtCvUnit maxY;
  706. _DtCvUnit botY;
  707. _DtCvSelectData next;
  708. _DtCvSegPts *newPt;
  709. _DtCvSegmentI *pSeg;
  710. _DtCvDspLine *lines = canvas->txt_lst;
  711. *ret_segs = NULL;
  712. if (beg->x == -1)
  713. return _DtCvSTATUS_NONE;
  714. /*
  715. * make sure the selection points are in the correct order.
  716. */
  717. CheckAndSwitchPoints(beg, end);
  718. /*
  719. * clear the processed bit
  720. */
  721. for (cnt = 0; cnt < canvas->txt_cnt; cnt++)
  722. _DtCvClearProcessed(lines[cnt]);
  723. /*
  724. * initialize the working structure
  725. * mark all the lines outside the selection regiion as invalid
  726. */
  727. next = *beg;
  728. MarkLinesOutsideBoundary(canvas, next.y, next.x, end->y, end->x);
  729. /*
  730. * start the minimum and maximum Y at this location.
  731. */
  732. minY = next.y;
  733. maxY = end->y;
  734. /*
  735. * is there a line at this location?
  736. */
  737. if (next.line_idx == -1)
  738. {
  739. /*
  740. * find the first selected line within the region.
  741. */
  742. if (FindNextMinY(lines, canvas->txt_cnt, -1, &next.y) == False)
  743. processing = False; /* empty of any text */
  744. else
  745. {
  746. /*
  747. * now find the first line that is on this 'line' and
  748. * the number of lines.
  749. */
  750. next.x = 0;
  751. lineCnt = FindMinX(lines, canvas->txt_cnt, next.y, &next.line_idx);
  752. next.char_idx = 0;
  753. }
  754. }
  755. else /* find the number of lines on this 'line' */
  756. lineCnt = FindMinX(lines, canvas->txt_cnt, next.y, &cnt);
  757. /*
  758. * loop will there are segments to process
  759. */
  760. while (processing == True && result == 0)
  761. {
  762. /*
  763. * process the next line of text.
  764. */
  765. while (result == 0 && lineCnt > 0)
  766. {
  767. /*
  768. * for each segment in this line (that is selected)
  769. * create a segment point for it.
  770. */
  771. length = lines[next.line_idx].length;
  772. start = lines[next.line_idx].byte_index;
  773. /*
  774. * if this is the last line, shorten the length
  775. * by the ending index.
  776. */
  777. if (next.line_idx == end->line_idx)
  778. length = end->char_idx;
  779. /*
  780. * move through the line's segments until we
  781. * hit the segment starting the selection
  782. */
  783. pSeg = lines[next.line_idx].seg_ptr;
  784. count = next.char_idx;
  785. while (NULL != pSeg && 0 < count)
  786. {
  787. /*
  788. * get the byte count of this segment
  789. */
  790. _DtCvGetWidthOfSegment(canvas, pSeg, start, length,
  791. &cnt, NULL, NULL);
  792. /*
  793. * is the byte count of this segment larger than
  794. * the starting index of the selection? If not,
  795. * the selection is after this segment.
  796. */
  797. if (count >= cnt)
  798. {
  799. start = 0;
  800. length -= cnt;
  801. pSeg = pSeg->next_disp;
  802. }
  803. else
  804. {
  805. length -= count;
  806. start = start + count;
  807. }
  808. count -= cnt;
  809. }
  810. while (0 == result && NULL != pSeg && 0 < length)
  811. {
  812. /*
  813. * start with error condition. If the malloc works
  814. * the error result gets reset to valid.
  815. */
  816. result = -1;
  817. newPt = (_DtCvSegPts *) malloc (sizeof(_DtCvSegPts));
  818. if (NULL != newPt)
  819. {
  820. /*
  821. * indicate everything is okay.
  822. */
  823. result = 0;
  824. /*
  825. * get the width of this segment
  826. */
  827. _DtCvGetWidthOfSegment(canvas, pSeg, start, length,
  828. &cnt, NULL, NULL);
  829. /*
  830. * now set the segment point information and add it to the
  831. * array of segment points.
  832. */
  833. newPt->offset = start;
  834. newPt->len = cnt;
  835. newPt->segment = pSeg;
  836. *ret_segs = (_DtCvSegPts **) _DtCvAddPtrToArray(
  837. (void **) *ret_segs,
  838. (void *) newPt);
  839. if (NULL == *ret_segs)
  840. result = -1;
  841. pSeg = pSeg->next_disp;
  842. length -= cnt;
  843. start = 0;
  844. }
  845. }
  846. /*
  847. * does this line extend below the selection y?
  848. * if so, report it as the maximum y.
  849. */
  850. botY = lines[next.line_idx].baseline + lines[next.line_idx].descent;
  851. if (botY > maxY)
  852. maxY = botY;
  853. /*
  854. * indicate this line has been processed.
  855. */
  856. _DtCvSetProcessed(lines[next.line_idx]);
  857. /*
  858. * get the next line
  859. */
  860. next.char_idx = 0;
  861. lineCnt = FindMinX(lines, canvas->txt_cnt, next.y,
  862. &next.line_idx);
  863. }
  864. if (result == 0)
  865. {
  866. next.x = 0;
  867. processing = FindNextMinY(lines,canvas->txt_cnt, -1, &next.y);
  868. if (processing == True)
  869. lineCnt = FindMinX(lines,canvas->txt_cnt,next.y,&next.line_idx);
  870. }
  871. }
  872. /*
  873. * if no errors, add a null to the array
  874. */
  875. if (0 != result)
  876. {
  877. *ret_segs = (_DtCvSegPts **) _DtCvAddPtrToArray((void **) *ret_segs,
  878. (void *) NULL);
  879. if (NULL == *ret_segs)
  880. result = -1;
  881. }
  882. /*
  883. * if errors, free the segment points and return a bad status.
  884. */
  885. if (0 != result)
  886. {
  887. if (NULL != *ret_segs)
  888. {
  889. for (lineCnt = 0; NULL != (*ret_segs)[lineCnt]; lineCnt++)
  890. free((*ret_segs)[lineCnt]);
  891. free(*ret_segs);
  892. }
  893. return _DtCvSTATUS_BAD;
  894. }
  895. if (NULL != ret_y1)
  896. *ret_y1 = minY;
  897. if (NULL != ret_y2)
  898. *ret_y2 = minY;
  899. return _DtCvSTATUS_OK;
  900. }
  901. /******************************************************************************
  902. * Semi-Public Functions
  903. ******************************************************************************/
  904. /*****************************************************************************
  905. * Function: _DtCvDrawAreaWithFlags
  906. *
  907. *****************************************************************************/
  908. void
  909. _DtCvDrawAreaWithFlags (
  910. _DtCanvasStruct *canvas,
  911. _DtCvSelectData start,
  912. _DtCvSelectData end,
  913. _DtCvFlags old_flags,
  914. _DtCvFlags new_flags,
  915. _DtCvElemType trav_type,
  916. _DtCvPointer trav_data)
  917. {
  918. int i;
  919. int len;
  920. int count;
  921. int startChar;
  922. int lnkInd;
  923. _DtCvUnit dstX;
  924. _DtCvUnit topY;
  925. _DtCvUnit botY;
  926. _DtCvUnit superWidth;
  927. _DtCvUnit subWidth;
  928. _DtCvUnit superY;
  929. _DtCvUnit subY;
  930. _DtCvUnit scriptX;
  931. _DtCvUnit segWidth;
  932. _DtCvSegmentI *pSeg;
  933. _DtCvValue lstLinkVis;
  934. _DtCvValue lstWasSuper;
  935. _DtCvValue lstWasSub;
  936. _DtCvValue trimmed;
  937. _DtCvFlags flagMask = old_flags | new_flags;
  938. _DtCvFlags endFlag = flagMask & _DtCvTRAVERSAL_END;
  939. _DtCvDspLine *lines = canvas->txt_lst;
  940. /*
  941. * now use the flagMask to determine what else to look for.
  942. * I.e. if flagMask has _DtCvMARK_FLAG set, then it becomes
  943. * set to _DtCvSELECTED_FLAG and visa versa.
  944. */
  945. flagMask ^= (_DtCvSELECTED_FLAG | _DtCvMARK_FLAG);
  946. /*
  947. * strip the end flag from the other flags
  948. */
  949. new_flags &= ~(_DtCvTRAVERSAL_END);
  950. old_flags &= ~(_DtCvTRAVERSAL_END);
  951. if (Equal(start, end))
  952. return;
  953. for (i = 0; i < canvas->txt_cnt; i++)
  954. {
  955. topY = lines[i].baseline - lines[i].ascent;
  956. botY = lines[i].baseline + lines[i].descent;
  957. if (InRegion(topY, botY, start.y, end.y))
  958. {
  959. /*
  960. * get the start of the text.
  961. */
  962. lstLinkVis = False;
  963. lstWasSuper = False;
  964. lstWasSub = False;
  965. lnkInd = -1;
  966. dstX = _DtCvGetStartXOfLine(&(lines[i]), &pSeg);
  967. startChar = lines[i].byte_index;
  968. count = lines[i].length;
  969. while (pSeg != NULL && _DtCvIsSegNoop(pSeg))
  970. {
  971. startChar = 0;
  972. pSeg = pSeg->next_disp;
  973. }
  974. /*
  975. * advance the starting point
  976. */
  977. dstX = _DtCvAdvanceXOfLine(canvas, pSeg, dstX,
  978. &lnkInd, &lstLinkVis);
  979. /*
  980. * take into account super/sub scripting
  981. */
  982. dstX = _DtCvAdjustForSuperSub(canvas, pSeg, dstX, &scriptX,
  983. &superWidth, &superY, &subWidth, &subY,
  984. &lstWasSuper, &lstWasSub);
  985. /*
  986. * set this flag so that the first pass of 'while (cnt > 0)'
  987. * doesn't do it again.
  988. */
  989. trimmed = True;
  990. if (_DtCvStraddlesPt(start.y, topY, botY))
  991. {
  992. /*
  993. * skip this item?
  994. * I.E. is this line before the start or after the end?
  995. */
  996. if (canvas->txt_lst[i].max_x < start.x ||
  997. (end.y == start.y && end.x <= dstX) )
  998. continue;
  999. /*
  1000. * does this line start the mark/selection?
  1001. */
  1002. if (i == start.line_idx && start.x >= dstX)
  1003. {
  1004. int cnt = start.char_idx;
  1005. while (cnt > 0)
  1006. {
  1007. if (trimmed == False)
  1008. {
  1009. /*
  1010. * advance the starting point
  1011. */
  1012. dstX = _DtCvAdvanceXOfLine(canvas, pSeg, dstX,
  1013. &lnkInd, &lstLinkVis);
  1014. /*
  1015. * take into account super/sub scripting
  1016. */
  1017. dstX = _DtCvAdjustForSuperSub(canvas,
  1018. pSeg, dstX, &scriptX,
  1019. &superWidth, &superY, &subWidth, &subY,
  1020. &lstWasSuper, &lstWasSub);
  1021. }
  1022. /*
  1023. * take into account the length of the segment
  1024. */
  1025. _DtCvGetWidthOfSegment(canvas, pSeg,
  1026. startChar , cnt,
  1027. &len, &segWidth, &trimmed);
  1028. dstX += segWidth;
  1029. startChar += len;
  1030. if (trimmed == False)
  1031. {
  1032. startChar = 0;
  1033. pSeg = pSeg->next_disp;
  1034. }
  1035. trimmed = False;
  1036. cnt -= len;
  1037. }
  1038. count -= start.char_idx;
  1039. }
  1040. /*
  1041. * otherwise this line is after the line that starts
  1042. * the mark/selection. Stick with its start x.
  1043. */
  1044. }
  1045. /*
  1046. * does this straddle the end point?
  1047. */
  1048. if (_DtCvStraddlesPt(end.y, topY, botY))
  1049. {
  1050. /*
  1051. * does this start after the end of the mark/selection?
  1052. * if so, skip.
  1053. */
  1054. if (end.x <= dstX)
  1055. continue;
  1056. /*
  1057. * Does this segment end after the end of the mark/selection?
  1058. * If so, trim how much gets highlighted.
  1059. */
  1060. if (canvas->txt_lst[i].max_x > end.x)
  1061. count -= (lines[i].length - end.char_idx);
  1062. }
  1063. /*
  1064. * while there is something to draw (un)mark/selected.
  1065. */
  1066. old_flags = old_flags | _DtCvMARK_BEGIN;
  1067. new_flags = new_flags | _DtCvMARK_BEGIN;
  1068. while (count > 0)
  1069. {
  1070. /*
  1071. * the original count to render
  1072. */
  1073. len = count;
  1074. /*
  1075. * check for other marks and selection.
  1076. */
  1077. _DtCvCheckLineMarks(canvas, i, startChar - lines[i].byte_index,
  1078. count, dstX, flagMask,
  1079. &len, &old_flags, &new_flags);
  1080. /*
  1081. * if this is the last segment(s) of the (un)mark/selection
  1082. * set the end flags.
  1083. */
  1084. if (len == count)
  1085. {
  1086. new_flags |= (endFlag | _DtCvLINK_END | _DtCvMARK_END);
  1087. old_flags |= (endFlag | _DtCvLINK_END | _DtCvMARK_END);
  1088. }
  1089. /*
  1090. * draw the segments that are marked/unmarked.
  1091. */
  1092. dstX = _DtCvDrawSegments(canvas, lines[i],
  1093. pSeg, startChar , len, &lnkInd,
  1094. dstX, dstX, &scriptX,
  1095. &superWidth, &superY, &subWidth, &subY,
  1096. &lstWasSub, &lstWasSuper,
  1097. &lstLinkVis, old_flags, new_flags,
  1098. trav_type, trav_data);
  1099. /*
  1100. * modify the count by the length processed
  1101. */
  1102. count -= len;
  1103. /*
  1104. * did this do the entire length? If not, set the
  1105. * indexes ahead and do again.
  1106. */
  1107. if (count > 0)
  1108. _DtCvSkipLineChars(canvas, pSeg, startChar , count + len,
  1109. len, &startChar , &pSeg);
  1110. /*
  1111. * strip the any begin flags.
  1112. */
  1113. _DtCvRemoveBeginFlags(old_flags);
  1114. _DtCvRemoveBeginFlags(new_flags);
  1115. }
  1116. }
  1117. }
  1118. }
  1119. /*****************************************************************************
  1120. * Function: _DtCanvasGetSelectionPoints()
  1121. *
  1122. * Purpose: Retrieve the segments making up the selection.
  1123. *
  1124. *****************************************************************************/
  1125. _DtCvStatus
  1126. _DtCvGetMarkSegs (
  1127. _DtCanvasStruct *canvas,
  1128. _DtCvPointInfo ***ret_info)
  1129. {
  1130. int i;
  1131. *ret_info = NULL;
  1132. for (i = 0; i < canvas->mark_cnt; i++)
  1133. {
  1134. _DtCvPointInfo *nxtInfo;
  1135. /*
  1136. * allocate mark information structure
  1137. */
  1138. nxtInfo = (_DtCvPointInfo *) malloc (sizeof(_DtCvPointInfo));
  1139. if (NULL == nxtInfo)
  1140. return _DtCvSTATUS_BAD;
  1141. nxtInfo->client_data = canvas->marks[i].client_data;
  1142. if (_DtCvSTATUS_BAD == GetSegsInArea(canvas, &(canvas->marks[i].beg),
  1143. &(canvas->marks[i].end),
  1144. &(nxtInfo->segs),
  1145. NULL, NULL))
  1146. return _DtCvSTATUS_BAD;
  1147. *ret_info = (_DtCvPointInfo **) _DtCvAddPtrToArray((void **) *ret_info,
  1148. (void *) nxtInfo);
  1149. if (NULL == *ret_info)
  1150. return _DtCvSTATUS_BAD;
  1151. }
  1152. return _DtCvSTATUS_OK;
  1153. }
  1154. /******************************************************************************
  1155. * Public Functions
  1156. ******************************************************************************/
  1157. /*****************************************************************************
  1158. * Function: _DtCanvasGetSelection()
  1159. *
  1160. * Purpose: Indicate the end point for a selection.
  1161. *
  1162. *****************************************************************************/
  1163. _DtCvStatus
  1164. _DtCanvasGetSelection (
  1165. _DtCvHandle canvas_handle,
  1166. unsigned int mask,
  1167. _DtCvPointer *ret_select)
  1168. {
  1169. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  1170. *ret_select = NULL;
  1171. return(GetSelectedText(canvas, canvas->select_start, canvas->select_end,
  1172. mask, ret_select));
  1173. }
  1174. /*****************************************************************************
  1175. * Function: _DtCanvasProcessSelection()
  1176. *
  1177. * Purpose: Indicate an new point for a selection.
  1178. *
  1179. *****************************************************************************/
  1180. void
  1181. _DtCanvasProcessSelection (
  1182. _DtCvHandle canvas_handle,
  1183. _DtCvUnit x,
  1184. _DtCvUnit y,
  1185. _DtCvSelectMode mode)
  1186. {
  1187. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  1188. _DtCvSelectData temp;
  1189. switch (mode)
  1190. {
  1191. case _DtCvSELECTION_CLEAR:
  1192. CheckAndSwitchPoints(&(canvas->select_start),
  1193. &(canvas->select_end));
  1194. case _DtCvSELECTION_START:
  1195. _DtCvDrawAreaWithFlags(canvas, canvas->select_start,
  1196. canvas->select_end,
  1197. _DtCvSELECTED_FLAG, 0,
  1198. _DtCvBAD_TYPE, NULL);
  1199. canvas->select_start = defaultSelect;
  1200. if (mode == _DtCvSELECTION_START)
  1201. SearchForClosestLine(canvas, x, y, &(canvas->select_start));
  1202. canvas->select_end = canvas->select_start;
  1203. break;
  1204. case _DtCvSELECTION_END:
  1205. case _DtCvSELECTION_UPDATE:
  1206. SearchForClosestLine(canvas, x, y, &temp);
  1207. AdjustSelection (canvas, temp);
  1208. if (mode == _DtCvSELECTION_END)
  1209. CheckAndSwitchPoints(&(canvas->select_start),
  1210. &(canvas->select_end));
  1211. break;
  1212. }
  1213. }
  1214. /*****************************************************************************
  1215. * Function: _DtCanvasGetSelectionPoints()
  1216. *
  1217. * Purpose: Retrieve the segments making up the selection.
  1218. *
  1219. *****************************************************************************/
  1220. _DtCvStatus
  1221. _DtCanvasGetSelectionPoints (
  1222. _DtCvHandle canvas_handle,
  1223. _DtCvSegPts ***ret_segs,
  1224. _DtCvUnit *ret_y1,
  1225. _DtCvUnit *ret_y2)
  1226. {
  1227. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  1228. return (GetSegsInArea(canvas, &(canvas->select_start),
  1229. &(canvas->select_end), ret_segs, ret_y1, ret_y2));
  1230. }
  1231. /*****************************************************************************
  1232. * Function: _DtCanvasActivatePts()
  1233. *
  1234. * Purpose: Activate the points given.
  1235. *
  1236. *****************************************************************************/
  1237. _DtCvStatus
  1238. _DtCanvasActivatePts (
  1239. _DtCvHandle canvas_handle,
  1240. unsigned int mask,
  1241. _DtCvPointInfo *info,
  1242. _DtCvUnit *ret_y1,
  1243. _DtCvUnit *ret_y2)
  1244. {
  1245. int markIdx;
  1246. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  1247. _DtCvSelectData startSel = defaultSelect;
  1248. _DtCvSelectData endSel = defaultSelect;
  1249. _DtCvFlags flag;
  1250. _DtCvSegmentI *firstSeg;
  1251. #define REQUIRE_SEGS \
  1252. (_DtCvACTIVATE_MARK | _DtCvACTIVATE_SELECTION)
  1253. /*
  1254. * check to see if there is anything to do
  1255. */
  1256. if (0 == mask)
  1257. return _DtCvSTATUS_NONE;
  1258. if ((mask & _DtCvACTIVATE_MARK) && (mask & _DtCvDEACTIVATE))
  1259. return _DtCvSTATUS_BAD;
  1260. /*
  1261. * Convert the segments into starting and ending positions.
  1262. */
  1263. if (((mask & _DtCvDEACTIVATE) && NULL == info->client_data)
  1264. || (mask & REQUIRE_SEGS))
  1265. {
  1266. if (NULL == info || NULL == info->segs ||
  1267. _DtCvSTATUS_BAD == _DtCvCvtSegsToPts(canvas, info->segs,
  1268. &startSel, &endSel,
  1269. ret_y1, ret_y2, &firstSeg))
  1270. return _DtCvSTATUS_BAD;
  1271. }
  1272. /*
  1273. * Activate as a selection
  1274. */
  1275. if (mask & _DtCvACTIVATE_SELECTION)
  1276. {
  1277. _DtCanvasProcessSelection (canvas_handle, 0, 0, _DtCvSELECTION_CLEAR);
  1278. canvas->select_start = startSel;
  1279. canvas->select_end = endSel;
  1280. _DtCvDrawAreaWithFlags (canvas, startSel, endSel,
  1281. 0, _DtCvSELECTED_FLAG,
  1282. _DtCvBAD_TYPE, NULL);
  1283. }
  1284. /*
  1285. * Activate as a mark
  1286. */
  1287. if (mask & _DtCvACTIVATE_MARK)
  1288. {
  1289. int travIdx;
  1290. _DtCvUnit x;
  1291. _DtCvUnit y;
  1292. _DtCvUnit width;
  1293. _DtCvUnit height;
  1294. markIdx = _DtCvAddToMarkList(canvas, info->client_data,
  1295. _DtCvIsMarkMaskOn(mask), &startSel, &endSel);
  1296. if (-1 == markIdx)
  1297. return _DtCvSTATUS_BAD;
  1298. /*
  1299. * now put the mark in the traversal list and merge it into the
  1300. * proper place.
  1301. */
  1302. travIdx = _DtCvGetNextTravEntry(canvas);
  1303. if (-1 == travIdx
  1304. || 0 != _DtCvSetTravEntryInfo(canvas, travIdx,
  1305. _DtCvTraversalMark, firstSeg,
  1306. markIdx, _DtCvTRUE)
  1307. || 0 != _DtCvCalcMarkPos(canvas, markIdx,
  1308. &x, &y, &width, &height)
  1309. || 0 != _DtCvSetTravEntryPos(canvas, travIdx,
  1310. x, y, width, height))
  1311. return _DtCvSTATUS_BAD;
  1312. _DtCvSortTraversalList(canvas, _DtCvTRUE);
  1313. /*
  1314. * draw these segments marked.
  1315. */
  1316. flag = _DtCvMARK_FLAG;
  1317. if (_DtCvTRUE == canvas->marks[markIdx].on)
  1318. flag |= _DtCvMARK_ON;
  1319. _DtCvDrawAreaWithFlags (canvas, startSel, endSel,
  1320. 0, flag,
  1321. _DtCvBAD_TYPE, NULL);
  1322. }
  1323. /*
  1324. * Clear the mark flag.
  1325. */
  1326. else if (mask & _DtCvDEACTIVATE)
  1327. {
  1328. int travIdx;
  1329. /*
  1330. * is there anything to deacivate?
  1331. */
  1332. if (NULL == canvas->marks || 0 == canvas->mark_cnt)
  1333. return _DtCvSTATUS_BAD;
  1334. /*
  1335. * was client data specified? If so, then look for it and ignore
  1336. * the segment data.
  1337. */
  1338. markIdx = 0;
  1339. if (NULL != info->client_data)
  1340. {
  1341. while (markIdx < canvas->mark_cnt &&
  1342. canvas->marks[markIdx].client_data != info->client_data)
  1343. markIdx++;
  1344. /*
  1345. * initialize the selection points
  1346. */
  1347. if (markIdx < canvas->mark_cnt)
  1348. {
  1349. startSel = canvas->marks[markIdx].beg;
  1350. endSel = canvas->marks[markIdx].end;
  1351. }
  1352. }
  1353. /*
  1354. * look for the marked set using the segments.
  1355. */
  1356. else
  1357. {
  1358. while (markIdx < canvas->mark_cnt
  1359. && startSel.line_idx != canvas->marks[markIdx].beg.line_idx
  1360. && startSel.char_idx != canvas->marks[markIdx].beg.char_idx
  1361. && endSel.line_idx != canvas->marks[markIdx].end.line_idx
  1362. && endSel.line_idx != canvas->marks[markIdx].end.char_idx)
  1363. markIdx++;
  1364. }
  1365. if (markIdx >= canvas->mark_cnt)
  1366. return _DtCvSTATUS_BAD;
  1367. /*
  1368. * draw these segments unmarked.
  1369. */
  1370. flag = _DtCvMARK_FLAG;
  1371. if (_DtCvTRUE == canvas->marks[markIdx].on)
  1372. flag |= _DtCvMARK_ON;
  1373. canvas->marks[markIdx].on = _DtCvFALSE;
  1374. _DtCvDrawAreaWithFlags (canvas, startSel, endSel, flag, 0,
  1375. _DtCvBAD_TYPE, NULL);
  1376. /*
  1377. * remove the mark from the traversal list
  1378. *
  1379. * first find the traversal entry of the mark and adjust any
  1380. * traversal mark index values to reflect that the mark
  1381. * list is about to shrink by 1.
  1382. */
  1383. for (travIdx = 0; _DtCvTraversalMark != canvas->trav_lst[travIdx].type
  1384. || markIdx != canvas->trav_lst[travIdx].idx; travIdx++)
  1385. {
  1386. /*
  1387. * is this mark after the one being removed?
  1388. * if so, decrease its index because it's about to move.
  1389. */
  1390. if (_DtCvTraversalMark == canvas->trav_lst[travIdx].type &&
  1391. markIdx < canvas->trav_lst[travIdx].idx)
  1392. canvas->trav_lst[travIdx].idx--;
  1393. }
  1394. /*
  1395. * move the list of traversal entries to eliminate the mark entry.
  1396. */
  1397. while (travIdx + 1 < canvas->trav_cnt)
  1398. {
  1399. canvas->trav_lst[travIdx] = canvas->trav_lst[travIdx + 1];
  1400. /*
  1401. * is this a mark after the one being removed?
  1402. * if so, decrease it's index because it's about to move.
  1403. */
  1404. if (_DtCvTraversalMark == canvas->trav_lst[travIdx].type &&
  1405. markIdx < canvas->trav_lst[travIdx].idx)
  1406. canvas->trav_lst[travIdx].idx--;
  1407. travIdx++;
  1408. }
  1409. /*
  1410. * update the traversal count and back up to the previous traversal
  1411. * if the mark was at the end of the traversal list.
  1412. */
  1413. canvas->trav_cnt--;
  1414. if (canvas->cur_trav >= canvas->trav_cnt)
  1415. canvas->cur_trav--;
  1416. /*
  1417. * move the list of marks up
  1418. */
  1419. while (markIdx + 1 < canvas->mark_cnt)
  1420. {
  1421. canvas->marks[markIdx] = canvas->marks[markIdx + 1];
  1422. markIdx++;
  1423. }
  1424. canvas->mark_cnt--;
  1425. }
  1426. else if ((_DtCvACTIVATE_MARK_ON | _DtCvACTIVATE_MARK_OFF) & mask)
  1427. {
  1428. markIdx = 0;
  1429. if (NULL != info && NULL != info->client_data)
  1430. {
  1431. while (markIdx < canvas->mark_cnt &&
  1432. canvas->marks[markIdx].client_data != info->client_data)
  1433. markIdx++;
  1434. /*
  1435. * was a mark with this client data found?
  1436. */
  1437. if (markIdx >= canvas->mark_cnt)
  1438. return _DtCvSTATUS_BAD;
  1439. }
  1440. else
  1441. {
  1442. /*
  1443. * are there any traversals? Is the current one sitting on a mark?
  1444. */
  1445. if (0 == canvas->trav_cnt || -1 == canvas->cur_trav ||
  1446. _DtCvTraversalMark != canvas->trav_lst[canvas->cur_trav].type)
  1447. return _DtCvSTATUS_BAD;
  1448. /*
  1449. * get the mark index
  1450. */
  1451. markIdx = canvas->trav_lst[canvas->cur_trav].idx;
  1452. }
  1453. /*
  1454. * is this different than what it is set at now? If not, do nothing.
  1455. */
  1456. if (_DtCvIsMarkMaskOn(mask) == canvas->marks[markIdx].on)
  1457. return _DtCvSTATUS_NONE;
  1458. /*
  1459. * set to mask value.
  1460. */
  1461. canvas->marks[markIdx].on = _DtCvIsMarkMaskOn(mask);
  1462. /*
  1463. * set the flags correctly.
  1464. */
  1465. flag = _DtCvMARK_FLAG;
  1466. if (_DtCvTRUE == canvas->marks[markIdx].on)
  1467. flag |= _DtCvMARK_ON;
  1468. if (_DtCvTRUE == canvas->trav_on &&
  1469. markIdx == canvas->trav_lst[canvas->cur_trav].idx)
  1470. flag |= _DtCvTRAVERSAL_FLAG;
  1471. /*
  1472. * draw the mark opposite what it was
  1473. */
  1474. _DtCvDrawAreaWithFlags (canvas, canvas->marks[markIdx].beg,
  1475. canvas->marks[markIdx].end,
  1476. (flag ^ _DtCvMARK_ON), flag,
  1477. _DtCvBAD_TYPE, NULL);
  1478. }
  1479. return _DtCvSTATUS_OK;
  1480. }
  1481. /*****************************************************************************
  1482. * Function: _DtCanvasGetMarkPositions()
  1483. *
  1484. * Purpose: Return the position in the canvas of the marks.
  1485. *
  1486. *****************************************************************************/
  1487. _DtCvStatus
  1488. _DtCanvasGetMarkPositions (
  1489. _DtCvHandle canvas_handle,
  1490. _DtCvMarkPos ***ret_pos)
  1491. {
  1492. int i;
  1493. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  1494. _DtCvMarkPos *nextPos;
  1495. _DtCvMarkData *markLst = canvas->marks;
  1496. *ret_pos = NULL;
  1497. if (0 == canvas->mark_cnt)
  1498. return _DtCvSTATUS_NONE;
  1499. for (i = 0; i < canvas->mark_cnt; i++, markLst++)
  1500. {
  1501. /*
  1502. * malloc memory for the information
  1503. */
  1504. nextPos = (_DtCvMarkPos *) malloc (sizeof(_DtCvMarkPos));
  1505. if (NULL == nextPos)
  1506. return _DtCvSTATUS_BAD;
  1507. /*
  1508. * client data and baselines
  1509. */
  1510. nextPos->client_data = markLst->client_data;
  1511. nextPos->baseline1 = canvas->txt_lst[markLst->beg.line_idx].baseline;
  1512. nextPos->baseline2 = canvas->txt_lst[markLst->end.line_idx].baseline;
  1513. /*
  1514. * top left corner
  1515. */
  1516. nextPos->x1 = markLst->beg.x;
  1517. nextPos->y1 = nextPos->baseline1 -
  1518. canvas->txt_lst[markLst->beg.line_idx].ascent;
  1519. /*
  1520. * bottom right corner
  1521. */
  1522. nextPos->x2 = markLst->end.x;
  1523. nextPos->y2 = nextPos->baseline2 +
  1524. canvas->txt_lst[markLst->end.line_idx].descent;
  1525. *ret_pos = (_DtCvMarkPos **) _DtCvAddPtrToArray((void **) *ret_pos,
  1526. (void *) nextPos);
  1527. if (NULL == *ret_pos)
  1528. return _DtCvSTATUS_BAD;
  1529. }
  1530. return _DtCvSTATUS_OK;
  1531. }