12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: LayoutUtil.c /main/26 1996/11/06 12:25:09 cde-hp $ */
- /************************************<+>*************************************
- ****************************************************************************
- **
- ** File: LayoutUtil.c
- **
- ** Project: Cde DtHelp
- **
- ** Description:
- **
- ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
- **
- ** (c) Copyright 1993, 1994 Hewlett-Packard Company
- ** (c) Copyright 1993, 1994 International Business Machines Corp.
- ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
- ** (c) Copyright 1993, 1994 Novell, Inc.
- **
- **
- **
- ****************************************************************************
- ************************************<+>*************************************/
- /*
- * system includes
- */
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
- /*
- * Canvas Engine includes
- */
- #include "CanvasP.h"
- #include "CanvasSegP.h"
- /*
- * private includes
- */
- #include "CanvasI.h"
- #include "CvStringI.h"
- #include "LayoutUtilI.h"
- #include "StringFuncsI.h"
- #include "VirtFuncsI.h"
- /******************************************************************************
- *
- * Private Defines
- *
- *****************************************************************************/
- #define GROW_SIZE 10
- #define CheckFormat(x) \
- (((x)->format_y == -1 || (x)->format_y > (x)->y_pos) ? False : True)
- /******************************************************************************
- *
- * Private Variables
- *
- *****************************************************************************/
- static char *OneByteCantBeginList = "])}`\"\'.,;?:!";
- static char *OneByteCantEndList = "[({`\"";
- static _DtCvLayoutInfo DefLayInfo =
- {
- NULL, /* _DtCvSegmentI *line_seg; */
- 0, /* unsigned int line_start; */
- 0, /* unsigned int line_bytes; */
- 0, /* _DtCvUnit cur_len; */
- 0, /* _DtCvUnit max_x_pos; */
- 0, /* _DtCvUnit cur_max_x; */
- 0, /* _DtCvUnit y_pos; */
- 0, /* _DtCvUnit text_x_pos; */
- 0, /* _DtCvUnit leading; */
- -1, /* int lst_hyper; */
- _CEFORMAT_ALL, /* int format_y; */
- -1, /* int join_line; */
- FALSE, /* _DtCvValue lst_vis; */
- FALSE, /* _DtCvValue join; */
- FALSE, /* _DtCvValue align_flag; */
- NULL, /* const char *align_char; */
- -1, /* _DtCvUnit align_pos; */
- 0, /* int delayed_search_saves */
- };
- static const _DtCvSelectData DefSelectData = { -1, -1, -1, -1 };
- static const _DtCvTraversalInfo DefTravData =
- {
- _DtCvFALSE /* active */,
- _DtCvTraversalNone /* type */,
- -1 /* idx */,
- 0 /* x_pos */,
- 0 /* y_pos */,
- 0 /* width */,
- 0 /* height */,
- NULL /* *seg_ptr */
- };
- /******************************************************************************
- *
- * Private Functions
- *
- *****************************************************************************/
- /******************************************************************************
- * Function: IsTrueMultiByte
- *
- * Returns: True if the character is a multibyte character
- * False if the character is a single byte character.
- *****************************************************************************/
- static _DtCvValue
- IsTrueMultiByte (wchar_t wc_char)
- {
- char buf[MB_LEN_MAX];
- /*
- * check to see if this is a one byte character
- * There might not be a multibyte list for this locale.
- * Can't break on single byte characters.
- */
- if (1 != wctomb(buf, wc_char))
- return True;
- return False;
- }
- /******************************************************************************
- * Function: CheckList
- *
- * Returns: True if the character matches one of the characters in
- * the MultiCantEndList.
- * False if the character does not match an item in
- * the MultiCantEndList.
- *****************************************************************************/
- static _DtCvValue
- CheckList (
- wchar_t wc_char,
- const wchar_t *list)
- {
- /*
- * check the multibyte list for the character
- */
- if (list != NULL)
- {
- while ('\0' != *list)
- {
- /*
- * it matches, return true
- */
- if (*list == wc_char)
- return True;
- list++;
- }
- }
- return False;
- }
- /*****************************************************************************
- * Function: static int CompareTraversalPos (_DtCvHandle canvas);
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- static int
- CompareTraversalPos (
- const void *a,
- const void *b)
- {
- _DtCvTraversalInfo *linkA = (_DtCvTraversalInfo *) a;
- _DtCvTraversalInfo *linkB = (_DtCvTraversalInfo *) b;
- _DtCvUnit centA = linkA->y_pos + (linkA->height >> 1);
- _DtCvUnit centB = linkB->y_pos + (linkB->height >> 1);
- if (linkA->y_pos + linkA->height < centB && centA < linkB->y_pos)
- return -1;
- if (linkB->y_pos + linkB->height < centA && centB < linkA->y_pos)
- return 1;
- if (linkA->x_pos != linkB->x_pos)
- return ((linkA->x_pos < linkB->x_pos) ? -1 : 1);
- if (linkA->y_pos != linkB->y_pos)
- return ((linkA->y_pos < linkB->y_pos) ? -1 : 1);
- if (linkA->height != linkB->height)
- return ((linkA->height < linkB->height) ? -1 : 1);
- if (linkA->width != linkB->width)
- return ((linkA->width < linkB->width) ? -1 : 1);
- return 0;
- }
- /******************************************************************************
- *
- * Private Layout Utility Functions
- *
- *****************************************************************************/
- /******************************************************************************
- * Function: void _DtCvInitLayoutInfo ()
- *
- * Parameters:
- *
- * Returns: Nothing.
- *
- *****************************************************************************/
- void
- _DtCvInitLayoutInfo (
- _DtCanvasStruct *canvas,
- _DtCvLayoutInfo *layout)
- {
- *layout = DefLayInfo;
- layout->y_pos = canvas->metrics.top_margin;
- }
- /******************************************************************************
- * Function: int _DtCvGetTraversalWidth ()
- *
- * Parameters:
- *
- * Returns: The total amount of space to add before and after the
- * segment to take into account traversal/link metrics on
- * this segment including any necessary to 'close' out the
- * link on the previous segment.
- *
- *****************************************************************************/
- int
- _DtCvGetTraversalWidth (
- _DtCanvasStruct *canvas,
- _DtCvSegmentI *p_seg,
- int lst_hyper)
- {
- int value = 0;
- int lnkBefore = 0;
- int lnkAfter = 0;
- /*
- * does this segment have a different link than the previous one?
- */
- if (lst_hyper != p_seg->link_idx)
- {
- /*
- * is the link visible?
- */
- if (_DtCvIsSegVisibleLink(p_seg))
- {
- /*
- * get the visible link metrics
- */
- lnkBefore = canvas->link_info.space_before;
- lnkAfter = canvas->link_info.space_after;
- }
- if (_DtCvIsSegALink(p_seg))
- {
- /*
- * if the last 'link' was really a link, close it out by
- * leaving room for the traversal and link end indicators
- */
- if (lst_hyper != -1)
- value += (canvas->traversal_info.space_after + lnkAfter);
- /*
- * leave space for the traversal/link begin and end
- * indicators for this segment.
- */
- value += (canvas->traversal_info.space_before
- + canvas->traversal_info.space_after
- + lnkBefore
- + lnkAfter);
- }
- }
- return value;
- }
- /******************************************************************************
- * Function: _DtCvAddLines
- *
- * makes sure the last x number of lines are blank.
- *****************************************************************************/
- void
- _DtCvAddSpace (
- _DtCvUnit number,
- _DtCvUnit *ret_y)
- {
- /*
- * anything to do?
- */
- if (0 >= number)
- return;
- /*
- * adjust the global Y position to allow the extra room
- */
- *ret_y = *ret_y + number;
- }
- /******************************************************************************
- * Function: CheckOneByteCantEndList
- *
- * Returns: True if the character matches one of the characters in
- * the OneByteCantEndList.
- * False if the character does not match an item in
- * the OneByteCantEndList.
- *****************************************************************************/
- _DtCvValue
- _DtCvCheckOneByteCantEndList (
- char c,
- char *cant_end_list)
- {
- int i;
- for (i = 0; cant_end_list[i]; i++)
- if (cant_end_list[i] == c)
- return True;
- return False;
- }
- /******************************************************************************
- * Function: CheckOneByteCantBeginList
- *
- * Returns: True if the character matches one of the characters in
- * the OneByteCantBeginList.
- * False if the character does not match an item in
- * the OneByteCantBeginList.
- *****************************************************************************/
- _DtCvValue
- _DtCvCheckOneByteCantBeginList (
- char c,
- char *cant_begin_list)
- {
- int i;
- for (i = 0; cant_begin_list[i]; i++)
- if (cant_begin_list[i] == c)
- return True;
- return False;
- }
- /******************************************************************************
- * Function: CheckLineSyntax
- *
- * Returns: True if the segment can end a line.
- * False if the segment can not end a line.
- *
- * Purpose: Checks the line syntax. Will not allow a segment to end
- * a line if:
- * the segment does not end with a hypen.
- * the segment does not end with a space and the
- * next segment does not begin with a space.
- * the segment ends with a two byte characters that
- * can not end a line.
- * The next segment starts with a two byte character
- * that can not begin a line.
- * the segment ends with an one-byte open type and
- * the next segment starts with a
- * two byte character.
- * the segment ends with a two byte character and
- * the next segment starts with a one-byte
- * close type.
- * the next segment is a non-breaking string or region.
- *
- *****************************************************************************/
- _DtCvValue
- _DtCvCheckLineSyntax (
- _DtCanvasStruct *canvas,
- _DtCvSegmentI *pSeg,
- int start,
- int str_len,
- _DtCvValue skip_hypen_ck)
- {
- int myStrLen = 0;
- int wcFlag = 0;
- void *pChar = NULL;
- wchar_t nextChar;
- wchar_t lastChar = 0;
- _DtCvValue lstCharMb = False;
- _DtCvValue nxtCharMb = False;
- /*
- * while this is a marker or a noop without a end-of-line, go to the
- * next segment.
- */
- while (NULL != pSeg && (_DtCvIsSegMarker(pSeg) ||
- (_DtCvIsSegNoop(pSeg) && !_DtCvIsSegNewLine(pSeg))))
- pSeg = pSeg->next_seg;
- /*
- * if this segment is null or not a string or region, stop the
- * test right now.
- */
- if (pSeg == NULL || !(_DtCvIsSegString(pSeg) || _DtCvIsSegRegion(pSeg)))
- return True;
- /*
- * Get the string segment stats
- */
- if (_DtCvIsSegString(pSeg))
- {
- wcFlag = _DtCvIsSegWideChar(pSeg);
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg), wcFlag, start);
- myStrLen = _DtCvStrLen (pChar, wcFlag);
- }
- /*
- * if this is a region or a string segment (at the end of its string)
- * and it has a newline on it, then it can end a line.
- */
- if ((_DtCvIsSegRegion(pSeg) ||
- (_DtCvIsSegString(pSeg) && myStrLen == str_len))
- && (_DtCvIsSegNewLine (pSeg) || pSeg->next_seg == NULL))
- return True;
- /*
- * if this is a region, then check it's breaking flag.
- */
- if (_DtCvIsSegRegion(pSeg))
- {
- if (_DtCvIsSegNonBreakingChar(pSeg))
- return False;
- return True;
- }
- /*
- * so, to get this far, this is a string segment.
- *
- * Problems with indexing?
- */
- if (str_len <= 0)
- return True;
- /*
- * do we need to check the last character in the string?
- * If skip_hypen_ck is true, it means that 'lastChar' would be a hypen.
- */
- if (False == skip_hypen_ck)
- {
- /*
- * this region is a string, get its string information.
- */
- lastChar = _DtCvChar(pChar, wcFlag, str_len - 1);
- /*
- * check to make sure the last character is a valid last
- * character.
- */
- if (' ' == lastChar || '-' == lastChar)
- return True;
- /*
- * If this string is a multi-byte, check the list of multi-bytes
- * that can't end a line. If one is found it can't end a line.
- */
- if (wcFlag &&
- CheckList(lastChar, canvas->locale.cant_end_chars) == True)
- return False;
- /*
- * so at the end of these tests, the last character is
- * -) not a blank.
- * -) not a hypen.
- * -) either a single byte character or multibyte character
- * that can end the line (including a single byte in
- * wide char form).
- *
- * set the flag for the type of character lastChar is.
- * if skip_hypen_ck was True, then lstCharMb remains False
- * which is logical since it means that the caller has already
- * processed a hypen (a single byte character).
- */
- lstCharMb = IsTrueMultiByte(lastChar);
- }
- /*
- * Check for more characters in the string and
- * check its next character for breakable space.
- */
- if (myStrLen > str_len)
- {
- /*
- * go to the next character.
- */
- nextChar = _DtCvChar(pChar, wcFlag, str_len);
- /*
- * Is it a valid break point?
- */
- if (' ' == nextChar)
- return True;
- /*
- * set the multibyte flag for the next character
- */
- nxtCharMb = IsTrueMultiByte(nextChar);
- /*
- * If this is wide char string, check the list of multi-byte
- * that can't begin a line.
- *
- * But only if the last character wasn't a hypen! Otherwise
- * it's a character after a hypen and should not be broken on.
- *
- * if this character is in the 'cannot begin line' list, then it
- * can't be broken on (a return value of true). (A wide char
- * encoding of a single byte character should come back as False
- * as long as the character is not in the list.)
- *
- * Have to double check to make sure it is a multibyte
- * character (want it to go through the CheckMulti list just in
- * case it's specified in there, before eliminating it).
- */
- if (False == skip_hypen_ck && wcFlag
- && CheckList(nextChar,canvas->locale.cant_begin_chars) == False
- && True == nxtCharMb)
- return True;
- /*
- * either the character is after a hypen (starting a line) OR it
- * is a multibyte character in the 'cannot begin a line' list OR
- * it is a single byte character. Therefore, this is a
- * nonbreakable character.
- */
- return False;
- }
- /*
- * We were at the last character of the string.
- * go to the next segment and see if it can start a new line.
- */
- do
- {
- pSeg = pSeg->next_seg;
- } while (pSeg != NULL && (_DtCvIsSegMarker(pSeg) ||
- (_DtCvIsSegNoop (pSeg) && !(_DtCvIsSegNewLine(pSeg)))));
- /*
- * If there isn't another valid segment, then the original segment
- * can end the line.
- */
- if (pSeg == NULL || !(_DtCvIsSegString(pSeg) || _DtCvIsSegRegion(pSeg)))
- return True;
- /*
- * if the last if fell through, then pSeg is a string or region.
- * check to see if you can break on it.
- */
- if (_DtCvIsSegNonBreakingChar(pSeg))
- return False;
- /*
- * if the last if fell through, then this is a breaking string or
- * region. Therefore, if a region, you can break on it.
- */
- if (_DtCvIsSegRegion(pSeg))
- return True;
- /*
- * To get this far, the next segment must be a string. Check the
- * first character of the string to see if it can start a new line.
- */
- nextChar = _DtCvChar(_DtCvStringOfStringSeg(pSeg),
- _DtCvIsSegWideChar(pSeg), 0);
- if (' ' == nextChar)
- return True;
- /*
- * If the previous character was a single byte character (or a hypen),
- * it couldn't end a line. If this is a single byte string, then
- * this string can't start a line......
- */
- if (_DtCvIsSegRegChar(pSeg) &&
- (True == skip_hypen_ck || False == lstCharMb))
- return False;
- /*
- * If this is multi-byte, check the list of multi-byte
- * that can't begin a line.
- */
- if (_DtCvIsSegWideChar(pSeg))
- {
- /*
- * plus checking the 'can not begin a line' list, check
- * if the previous character was a hypen, then this can't be
- * broken on either.
- */
- if (True == skip_hypen_ck ||
- CheckList(nextChar, canvas->locale.cant_begin_chars) == True)
- return False;
- /*
- * if the previous character was a multi-byte and this
- * character is a multibyte, then it is a valid break.
- */
- nxtCharMb = IsTrueMultiByte(nextChar);
- if (True == lstCharMb && True == nxtCharMb)
- return True;
- }
- /*
- * if the last character was a single byte character, then there
- * is still more to check - 1 byte punctuation around multi-byte.
- */
- if (False == lstCharMb &&
- _DtCvCheckOneByteCantEndList((char)lastChar,OneByteCantEndList) == True)
- return False;
-
- /*
- * or was the last character a multibyte and is followed by single byte
- * punctuation?
- */
- if (True == lstCharMb && False == nxtCharMb &&
- _DtCvCheckOneByteCantBeginList((char)nextChar, OneByteCantBeginList)
- == True)
- return False;
- return True;
- }
- /******************************************************************************
- * Function: _DtCvGetNextWidth
- *
- * Purpose: Determines the width of the next legal segment.
- *
- * Returns: The width of the next legal segment.
- *
- *****************************************************************************/
- int
- _DtCvGetNextWidth (
- _DtCanvasStruct *canvas,
- int old_type,
- int lst_hyper,
- _DtCvSegmentI *pSeg,
- int start,
- _DtCvSegmentI *prev_seg,
- _DtCvSegmentI **nextSeg,
- int *nextStart,
- int *widthCount)
- {
- int result;
- int len = 0;
- int tLen;
- int wcFlag;
- int curWidth;
- int myLength;
- int nextLen = 0;
- void *pChar;
- char *tChar;
- _DtCvValue good_len;
- /*
- * pass over noops that don't have newlines and markers
- */
- while (pSeg != NULL && (_DtCvIsSegMarker(pSeg) ||
- (_DtCvIsSegNoop (pSeg) && !(_DtCvIsSegNewLine(pSeg)))))
- {
- pSeg = pSeg->next_seg;
- start = 0;
- }
- if (nextSeg != NULL)
- *nextSeg = pSeg;
- if (nextStart != NULL)
- *nextStart = start;
- /*
- * if the next segment is null or anything else but a string or region;
- * return that there is no more after this segment.
- */
- if (pSeg == NULL || !(_DtCvIsSegString(pSeg) || _DtCvIsSegRegion(pSeg)))
- return 0;
- /*
- * this segment is a region or string
- * check for region...anything left is a string.
- */
- if (_DtCvIsSegRegion(pSeg))
- {
- /*
- * can I break on this region
- */
- if (_DtCvIsSegNonBreakingChar(pSeg))
- {
- /*
- * no...set the lengths and continue
- */
- len = 1;
- curWidth = _DtCvWidthOfRegionSeg(pSeg);
- }
- else
- return 0;
- }
- /*
- * is this a non breaking string?
- */
- else if (_DtCvIsSegNonBreakingChar(pSeg))
- {
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
- _DtCvIsSegWideChar(pSeg), start);
- len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(pSeg));
- curWidth = _DtCvGetStringWidth (canvas, pSeg, pChar, len)
- + _DtCvGetTraversalWidth(canvas, pSeg, lst_hyper);
- }
- /*
- * so this is a string with possible breaks in it.
- */
- else
- {
- /*
- * get the string stats
- */
- wcFlag = _DtCvIsSegWideChar (pSeg);
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg), wcFlag, start);
- myLength = _DtCvStrLen (pChar, wcFlag);
-
- /*
- * if a single byte string, zoom through it looking for
- * specific breaking characters.
- */
- if (0 == wcFlag)
- {
- tChar = pChar;
- len = 0;
- do
- {
- /*
- * checking for a hypen or space
- */
- good_len = True;
- result = _DtCvStrcspn ((void *) tChar, " -", 0, &tLen);
- len += tLen;
-
- /*
- * check for '-'. Some of the possible combinations are:
- * -text
- * - text
- * -/text/
- * text/-text/
- * text-text
- * text text
- *
- * if it is the first character to check and there is no
- * previous segment, then it is starting a line and can
- * not be broken on.
- *
- * _DtCvStrcpn return 0 if one of the characters in the
- * test string was found.
- */
- if (0 == result && '-' == tChar[tLen] && 0 == len &&
- NULL == prev_seg &&
- _DtCvCheckLineSyntax(canvas,pSeg,start,1,True) == False)
- {
- len++;
- tLen++;
- tChar += tLen;
- good_len = False;
- }
- } while (!good_len);
-
- /*
- * found either a space or a hypen or null byte.
- * If we found a hypen, include it.
- */
- if ('-' == *tChar)
- len++;
-
- curWidth = _DtCvGetStringWidth (canvas, pSeg, pChar, len)
- + _DtCvGetTraversalWidth(canvas, pSeg, lst_hyper);
-
- /*
- * Did we find a space or hypen?
- * If not, can this segment stand alone?
- */
- if (result == 0 ||
- _DtCvCheckLineSyntax(canvas,pSeg,start,len,False) == True)
- {
- if (nextSeg != NULL)
- *nextSeg = pSeg;
- if (nextStart != NULL)
- *nextStart = start + len;
- if (widthCount != NULL)
- *widthCount = len;
- return curWidth;
- }
- }
- /*
- * multibyte (wide char string), look for a break the hard way.
- */
- else
- {
- len = 0;
- while (len < myLength)
- {
- len++;
- if (_DtCvCheckLineSyntax(canvas,pSeg,start,len,False) == True)
- {
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
- _DtCvIsSegWideChar(pSeg), start);
- curWidth = _DtCvGetStringWidth(canvas,pSeg,pChar,len)
- + _DtCvGetTraversalWidth(canvas,pSeg,lst_hyper);
-
- if (nextSeg != NULL)
- *nextSeg = pSeg;
- if (nextStart != NULL)
- *nextStart = start + len;
- if (widthCount != NULL)
- *widthCount = len;
- return curWidth;
- }
- }
-
- /*
- * Didn't find a smaller segment that satisfied the requirements.
- * Determine the length of the current segment.
- */
- curWidth = _DtCvGetStringWidth (canvas, pSeg, pChar, len)
- + _DtCvGetTraversalWidth(canvas, pSeg,
- lst_hyper);
- }
- }
- /*
- * sigh...need to go further...this segment can't end a line
- * either.
- */
- prev_seg = pSeg;
- pSeg = pSeg->next_seg;
- if (pSeg != NULL)
- {
- start = 0;
- curWidth += _DtCvGetNextWidth (canvas,
- _DtCvPrimaryTypeOfSeg (prev_seg), lst_hyper,
- pSeg, start, prev_seg,
- nextSeg, nextStart, &nextLen);
- }
- if (widthCount != NULL)
- *widthCount = len + nextLen;
- return (curWidth);
- }
- /******************************************************************************
- * Function: _DtCvSaveInfo
- *
- * Initializes a line table element to the segment it should display.
- *****************************************************************************/
- void
- _DtCvSaveInfo (
- _DtCanvasStruct *canvas,
- _DtCvLayoutInfo *layout,
- _DtCvUnit max_width,
- _DtCvUnit r_margin,
- _DtCvFrmtOption txt_justify)
- {
- /*****************************************************************
- * The ascent for a line is described as the number of units
- * above the baseline.
- *
- * The descent for a line is described as the number of units
- * below the baseline.
- *
- * Neither the ascent or decent value includes the baseline
- ****************************************************************/
- int len;
- int start = layout->line_start;
- int count = layout->line_bytes;
- long txtCnt = canvas->txt_cnt;
- _DtCvUnit maxAscent = 0;
- _DtCvUnit maxDescent = 0;
- _DtCvUnit maxRegion = 0;
- _DtCvUnit superY = 0;
- _DtCvUnit subY = 0;
- _DtCvUnit fontAscent;
- _DtCvUnit fontDescent;
- _DtCvValue fndLnk = False;
- _DtCvValue visLnk = False;
- void *pChar;
- _DtCvSegmentI *pSeg = layout->line_seg;
- if (txtCnt >= canvas->txt_max)
- {
- canvas->txt_max += GROW_SIZE;
- if (canvas->txt_lst)
- canvas->txt_lst = (_DtCvDspLine *) realloc (
- (void *) canvas->txt_lst,
- (sizeof(_DtCvDspLine) * canvas->txt_max));
- else
- canvas->txt_lst = (_DtCvDspLine *) malloc (
- (sizeof(_DtCvDspLine) * canvas->txt_max));
- /*
- * NOTE....should this routine return a value?
- * If (re)alloc error occurs, this simply ignores the problem.
- */
- if (canvas->txt_lst == NULL)
- {
- canvas->txt_max = 0;
- canvas->txt_cnt = 0;
- return;
- }
- }
- while (pSeg != NULL && count > 0)
- {
- /*
- * set which line will this segment sit on, iff this is the
- * first access to the segment.
- */
- if ((void *) -1 == pSeg->internal_use)
- pSeg->internal_use = (void *) txtCnt;
-
- /*
- * now get the segment's sizing so we can determine
- * the height and depth of the line.
- */
- len = 1;
- fontAscent = 0;
- fontDescent = 0;
- if (_DtCvIsSegVisibleLink(pSeg))
- visLnk = True;
- if (_DtCvIsSegALink(pSeg))
- fndLnk = True;
- /*
- * get the ascent and descent of the segment along with a length
- */
- if (_DtCvIsSegString(pSeg))
- {
- _DtCvFontMetrics(canvas,_DtCvFontOfStringSeg(pSeg),
- &fontAscent, &fontDescent, NULL, NULL, NULL);
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
- _DtCvIsSegWideChar(pSeg), start);
- len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(pSeg));
- if (len > count)
- len = count;
- }
- else if (_DtCvIsSegRegion(pSeg))
- {
- if (-1 == _DtCvAscentOfRegionSeg(pSeg))
- {
- if (maxRegion < _DtCvHeightOfRegionSeg(pSeg))
- maxRegion = _DtCvHeightOfRegionSeg(pSeg);
- }
- else
- {
- fontAscent = _DtCvAscentOfRegionSeg(pSeg);
- fontDescent = _DtCvHeightOfRegionSeg(pSeg) - fontAscent;
- }
- }
- /*
- * adjust the ascent and descent values by their subscript
- * or superscript adjustments.
- */
- if (_DtCvIsSegSuperScript(pSeg))
- {
- fontAscent += superY;
- fontDescent -= superY;
- if (_DtCvIsSegRegion(pSeg) && -1 == _DtCvAscentOfRegionSeg(pSeg)
- && maxRegion < _DtCvHeightOfRegionSeg(pSeg) + superY)
- maxRegion = _DtCvHeightOfRegionSeg(pSeg) + superY;
- }
- else if (_DtCvIsSegSubScript(pSeg))
- {
- fontAscent -= subY;
- fontDescent += subY;
- if (_DtCvIsSegRegion(pSeg) && -1 == _DtCvAscentOfRegionSeg(pSeg)
- && maxRegion < _DtCvHeightOfRegionSeg(pSeg) + subY)
- maxRegion = _DtCvHeightOfRegionSeg(pSeg) + subY;
- }
- else /* not a subscript or superscript */
- {
- /*
- * set up the super and sub script offsets for following
- * segments.
- */
- if (_DtCvIsSegString (pSeg))
- _DtCvFontMetrics(canvas,_DtCvFontOfStringSeg(pSeg),
- NULL, NULL, NULL, &superY, &subY);
- else if (_DtCvIsSegRegion(pSeg))
- {
- superY = _DtCvHeightOfRegionSeg(pSeg) * 4 / 10;
- subY = superY;
- }
- }
- /*
- * now determine the maximums for ascent and descent.
- */
- if (fontAscent > maxAscent)
- maxAscent = fontAscent;
- if (fontDescent > maxDescent)
- maxDescent = fontDescent;
- /*
- * decrement the count
- */
- count -= len;
- /*
- * If this segment terminates the paragraph
- * force the end of the loop.
- */
- pSeg = pSeg->next_disp;
- start = 0;
- }
- if (txt_justify == _DtCvJUSTIFY_RIGHT || _DtCvJUSTIFY_CENTER == txt_justify)
- {
- /*
- * justify the line.
- */
- _DtCvUnit workWidth = max_width - layout->text_x_pos -
- r_margin - layout->cur_len;
- if (txt_justify == _DtCvJUSTIFY_CENTER)
- workWidth = workWidth / 2;
- if (workWidth < 0)
- workWidth = 0;
- layout->text_x_pos += workWidth;
- }
- /*
- * adjust for any special characters found
- */
- if (maxRegion > maxAscent + maxDescent + 1)
- maxAscent = maxRegion - maxDescent - 1;
- /*
- * check to see if the max values have even been touched.
- */
- if (layout->line_bytes == 0 && maxAscent == 0 && maxDescent == 0)
- maxAscent = canvas->metrics.line_height;
- /*
- * adjust ascent and descent by the traversal and link info
- */
- maxDescent += layout->leading;
- if (fndLnk)
- {
- maxAscent += canvas->traversal_info.space_above;
- maxDescent += canvas->traversal_info.space_below;
- if (visLnk)
- {
- maxAscent += canvas->link_info.space_above;
- maxDescent += canvas->link_info.space_below;
- }
- }
- /*
- * save the line information, if there is a string here.
- */
- if (layout->line_bytes > 0)
- {
- canvas->txt_lst[txtCnt].processed = _DtCvFALSE;
- canvas->txt_lst[txtCnt].text_x = layout->text_x_pos;
- canvas->txt_lst[txtCnt].max_x = layout->text_x_pos;
- canvas->txt_lst[txtCnt].baseline = layout->y_pos + maxAscent;
- canvas->txt_lst[txtCnt].descent = maxDescent;
- canvas->txt_lst[txtCnt].ascent = maxAscent;
- canvas->txt_lst[txtCnt].byte_index = layout->line_start;
- canvas->txt_lst[txtCnt].length = layout->line_bytes;
- canvas->txt_lst[txtCnt].seg_ptr = layout->line_seg;
- canvas->txt_cnt++;
- }
- /*
- * blank line is one half the normal size line
- */
- else
- {
- maxAscent = (maxAscent + maxDescent) / 2;
- maxDescent = 0;
- }
- if (layout->text_x_pos + layout->cur_len > layout->cur_max_x)
- layout->cur_max_x = layout->text_x_pos + layout->cur_len;
- if (layout->text_x_pos + layout->cur_len > layout->max_x_pos)
- layout->max_x_pos = layout->text_x_pos + layout->cur_len;
- /*
- * zero the string info
- */
- layout->line_bytes = 0;
- layout->cur_len = 0;
- layout->lst_hyper = -1;
- layout->lst_vis = False;
- _DtCvSetJoinInfo(layout, False, -1);
- /*
- * adjust where the next line is positioned.
- */
- layout->y_pos = layout->y_pos + maxAscent + maxDescent + 1;
- }
- /******************************************************************************
- * Function: _DtCvCheckAddHyperToTravList
- *
- *****************************************************************************/
- void
- _DtCvCheckAddHyperToTravList (
- _DtCanvasStruct *canvas,
- _DtCvSegmentI *p_seg,
- _DtCvValue flag,
- _DtCvValue *lst_vis,
- int *lst_hyper,
- _DtCvUnit *cur_len)
- {
- int nxtHyper;
- int prevIdx;
- _DtCvValue junk;
- _DtCvUnit retLen = *cur_len;
- if (_DtCvIsSegALink (p_seg))
- {
- nxtHyper = _DtCvGetNextTravEntry(canvas);
- if (-1 == nxtHyper)
- /*
- * NOTE....should this routine return a value?
- * If (re)alloc error occurs, this simply ignores the problem.
- */
- return;
- prevIdx = nxtHyper - 1;
- if (prevIdx < 0
- || _DtCvTraversalLink != canvas->trav_lst[prevIdx].type
- || p_seg->link_idx != canvas->trav_lst[prevIdx].seg_ptr->link_idx)
- {
- /*
- * save this hypertext link in the traversal list
- */
- _DtCvSetTravEntryInfo (canvas, nxtHyper, _DtCvTraversalLink, p_seg,
- canvas->txt_cnt, _DtCvTRUE);
- }
- }
- /*
- * take into account the link metrics.
- */
- junk = _DtCvIsSegVisibleLink(p_seg);
- *lst_vis = _DtCvModifyXpos(canvas->link_info, p_seg, junk,
- *lst_vis, *lst_hyper,
- &retLen);
- /*
- * take into account the traversal metrics
- */
- junk = _DtCvIsSegALink(p_seg);
- (void) _DtCvModifyXpos(canvas->traversal_info, p_seg, junk,
- ((_DtCvValue) True), *lst_hyper,
- &retLen);
- *lst_hyper = p_seg->link_idx;
- if (_DtCvTRUE == flag)
- *cur_len = retLen;
- }
- /******************************************************************************
- * Function: ProcessStringSegment
- *
- * chops a string segment up until its completely used.
- *
- * Returns:
- * 0 if the entire string segment was processed.
- * 1 if the required number of lines were processed.
- *****************************************************************************/
- int
- _DtCvProcessStringSegment(
- _DtCanvasStruct *canvas,
- _DtCvLayoutInfo *lay_info,
- _DtCvUnit max_width,
- _DtCvUnit l_margin,
- _DtCvUnit r_margin,
- _DtCvSegmentI *cur_seg,
- unsigned int *cur_start,
- _DtCvFrmtOption txt_justify,
- _DtCvValue stat_flag)
- {
- _DtCvUnit workWidth;
- _DtCvUnit stringLen;
- _DtCvUnit textWidth;
- _DtCvUnit nWidth;
- _DtCvUnit spaceSize = 0;
- int oldType;
- int retStart;
- int retCount;
- wchar_t *wcp;
- void *pChar;
- char *strPtr;
- _DtCvValue done = False;
- _DtCvSegmentI *retSeg;
- if (NULL != _DtCvStringOfStringSeg(cur_seg))
- {
- if (lay_info->cur_len == 0)
- {
- lay_info->line_seg = cur_seg;
- lay_info->line_start = *cur_start;
- }
- if (*cur_start == 0 && (cur_seg->type & _DtCvSEARCH_FLAG))
- lay_info->delayed_search_saves++;
- oldType = _DtCvPrimaryTypeOfSeg (cur_seg);
- /*
- * is alignment in effect?
- */
- if (TRUE == lay_info->align_flag)
- {
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(cur_seg),
- _DtCvIsSegWideChar(cur_seg), *cur_start);
- nWidth = _DtCvStrcspn (pChar, lay_info->align_char,
- _DtCvIsSegWideChar(cur_seg),
- &stringLen);
- if (-1 == nWidth)
- return -1;
- /*
- * we got a valid length back, calculate the length
- */
- textWidth = 0;
- if (0 != stringLen)
- textWidth = _DtCvGetStringWidth(canvas,cur_seg,pChar,stringLen);
- /*
- * check to see if this a hypertext that needs
- * to be remembered.
- */
- _DtCvCheckAddHyperToTravList (canvas, cur_seg, _DtCvTRUE,
- &(lay_info->lst_vis),
- &(lay_info->lst_hyper),
- &(lay_info->cur_len));
- /*
- * update the length and position information
- * to skip past the characters before the alignment character.
- */
- lay_info->line_bytes += stringLen;
- lay_info->cur_len += (textWidth
- + _DtCvGetTraversalWidth(canvas,
- cur_seg, lay_info->lst_hyper));
- *cur_start += stringLen;
- /*
- * if we didn't find the character, check to see if this forces
- * a newline - honor it if it does. We'll check the next
- * string segment for the alignment character.
- */
- if (1 == nWidth && _DtCvIsSegNewLine (cur_seg)
- && lay_info->line_bytes)
- {
- _DtCvSaveInfo (canvas,lay_info,max_width,r_margin,txt_justify);
- while (lay_info->delayed_search_saves > 0) {
- _DtCvSetSearchEntryInfo(canvas, canvas->txt_cnt - 1);
- lay_info->delayed_search_saves--;
- }
- return 0;
- }
- /*
- * so we found the character, now get it's width.
- */
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(cur_seg),
- _DtCvIsSegWideChar(cur_seg), *cur_start);
- textWidth = _DtCvGetStringWidth(canvas, cur_seg, pChar, 1)
- + _DtCvGetTraversalWidth(canvas, cur_seg,
- lay_info->lst_hyper);
- /*
- * is this the second or more align position?
- * if so, need to shift the character to align with others.
- */
- if (lay_info->align_pos >
- lay_info->text_x_pos + lay_info->cur_len + textWidth / 2)
- lay_info->text_x_pos = lay_info->align_pos - lay_info->cur_len
- - textWidth / 2;
- /*
- * otherwise, does this exceed the previous alignments?
- * if so, the table processing should catch that we've
- * changed the alignment position and re-format the others.
- */
- else if (lay_info->align_pos <
- lay_info->text_x_pos + lay_info->cur_len + textWidth / 2)
- lay_info->align_pos =
- lay_info->text_x_pos + lay_info->cur_len + textWidth / 2;
- /*
- * indicate that the character has been found.
- */
- lay_info->align_flag = False;
- /*
- * check to see if this item can end a line.
- * if can't end the line, force a join for the next segment or
- * for the rest of this segment.
- */
- if (False == _DtCvCheckLineSyntax(canvas,cur_seg,*cur_start,1,False))
- lay_info->join = True;
- /*
- * update the length and position information to
- * include the character.
- */
- lay_info->line_bytes++;
- lay_info->cur_len += textWidth;
- *cur_start += 1;
- /*
- * check to see if this is the end of the segment.
- */
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(cur_seg),
- _DtCvIsSegWideChar(cur_seg), *cur_start);
- if ((_DtCvIsSegWideChar(cur_seg) && 0 == *((wchar_t *) pChar))
- ||
- (_DtCvIsSegRegChar(cur_seg) && '\0' == *((char *) pChar)))
- return 0;
- }
- while (1)
- {
- /*
- * recalculate the width
- */
- workWidth = max_width - lay_info->text_x_pos -
- lay_info->cur_len - r_margin;
- /*
- * adjust the character pointer and get the
- * length of the string.
- */
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(cur_seg),
- _DtCvIsSegWideChar(cur_seg), *cur_start);
- stringLen = _DtCvStrLen (pChar, _DtCvIsSegWideChar(cur_seg));
-
- /*
- * get the pixel width of the text string.
- */
- textWidth = _DtCvGetStringWidth(canvas,cur_seg,pChar,stringLen)
- + _DtCvGetTraversalWidth(canvas, cur_seg,
- lay_info->lst_hyper);
- /*
- * Will it fit in the current width?
- */
- if (stat_flag == True || textWidth <= workWidth)
- {
- /*
- * Yes, this segment or part of a segment can fit in the
- * current width. But can the last character of this
- * segment end a line and can the beginning of the next
- * segment start a new line?
- */
- if (stat_flag == True ||
- _DtCvCheckLineSyntax (canvas, cur_seg,
- *cur_start, stringLen, False) == TRUE)
- {
- /*
- * check to see if this a hypertext that needs
- * to be remembered.
- */
- _DtCvCheckAddHyperToTravList (canvas, cur_seg, _DtCvFALSE,
- &(lay_info->lst_vis),
- &(lay_info->lst_hyper),
- &(lay_info->cur_len));
- /*
- * The line syntax is good.
- * Update the global and width variables.
- */
- lay_info->line_bytes += stringLen;
- lay_info->cur_len += textWidth;
- _DtCvSetJoinInfo(lay_info,
- _DtCvIsSegNonBreakingChar(cur_seg),
- -1);
- /*
- * Check to see if this segment forces an end
- */
- if (_DtCvIsSegNewLine (cur_seg) && lay_info->line_bytes) {
- _DtCvSaveInfo (canvas, lay_info, max_width,
- r_margin, txt_justify);
- while (lay_info->delayed_search_saves > 0) {
- _DtCvSetSearchEntryInfo(canvas,
- canvas->txt_cnt - 1);
- lay_info->delayed_search_saves--;
- }
- }
- return 0;
- }
-
- /*
- * CheckLineSyntax says that either this line couldn't
- * end a line or the next segment couldn't start a line.
- * Therefore, find out how much of the next segment or
- * segments we need to incorporate to satisfy the Line
- * Syntax rules.
- */
- nWidth = _DtCvGetNextWidth (canvas, oldType,
- lay_info->lst_hyper,
- cur_seg->next_seg, 0, cur_seg,
- &retSeg, &retStart, &retCount);
- /*
- * will this segment + the next segment fit?
- */
- if (textWidth + nWidth <= workWidth)
- {
- /*
- * check to see if this a hypertext that needs
- * to be remembered.
- */
- _DtCvCheckAddHyperToTravList (canvas, cur_seg, _DtCvFALSE,
- &(lay_info->lst_vis),
- &(lay_info->lst_hyper),
- &(lay_info->cur_len));
- /*
- * YEAH Team!! It Fits!!
- *
- * Update the global and width variables.
- */
- lay_info->line_bytes += stringLen;
- lay_info->cur_len += textWidth;
- _DtCvSetJoinInfo(lay_info, False, -1);
-
- return 0;
- }
- }
-
- /*
- * the text width plus the next segment is tooo big
- * to fit. Reduce the current segment if possible
- */
- done = False;
- textWidth = 0;
- stringLen = 0;
- while (!done)
- {
- nWidth = _DtCvGetNextWidth (canvas, oldType,
- lay_info->lst_hyper,
- cur_seg, *cur_start, NULL,
- &retSeg, &retStart, &retCount);
- if (retSeg == cur_seg && textWidth + nWidth <= workWidth)
- {
- /*
- * check to see if this a hypertext that needs
- * to be remembered.
- */
- _DtCvCheckAddHyperToTravList (canvas, cur_seg, _DtCvFALSE,
- &(lay_info->lst_vis),
- &(lay_info->lst_hyper),
- &(lay_info->cur_len));
- _DtCvSetJoinInfo(lay_info, False, -1);
- *cur_start = retStart;
- stringLen += retCount;
- textWidth += nWidth;
- spaceSize = 0;
- /*
- * take into account a space if that is where it breaks.
- */
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(cur_seg),
- _DtCvIsSegWideChar(cur_seg),
- *cur_start);
- if ((_DtCvIsSegWideChar(cur_seg) &&
- (' ' == *((wchar_t *) pChar)))
- ||
- (_DtCvIsSegRegChar(cur_seg) &&
- (' ' == *((char *) pChar))))
- {
- spaceSize = _DtCvGetStringWidth(canvas,
- cur_seg, pChar, 1)
- + _DtCvGetTraversalWidth (canvas,
- cur_seg, lay_info->lst_hyper);
- textWidth += spaceSize;
- stringLen++;
- (*cur_start)++;
- }
- }
- else
- {
- /*
- * Done trying to find a segment that will
- * fit in the size given
- */
- done = True;
- }
- }
- /*
- * Update the global variables
- */
- lay_info->line_bytes += stringLen;
- lay_info->cur_len += textWidth;
- if (lay_info->join == True || lay_info->line_bytes == 0)
- {
- /*
- * This line would be empty if we followed the rules.
- * Or it would break a line improperly.
- * Force this onto the line.
- * check to see if this a hypertext that needs
- * to be remembered.
- */
- _DtCvCheckAddHyperToTravList (canvas, cur_seg, _DtCvTRUE,
- &(lay_info->lst_vis),
- &(lay_info->lst_hyper),
- &(lay_info->cur_len));
- /*
- * Couldn't find a smaller, have to
- * go with the larger segment.
- */
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(cur_seg),
- _DtCvIsSegWideChar(cur_seg),
- *cur_start);
- stringLen = _DtCvStrLen (pChar, _DtCvIsSegWideChar(cur_seg));
- if (retCount > 0 && retCount < stringLen)
- stringLen = retCount;
- lay_info->line_bytes += stringLen;
- lay_info->cur_len += (_DtCvGetStringWidth(canvas, cur_seg,
- pChar, stringLen)
- + _DtCvGetTraversalWidth (canvas,
- cur_seg, lay_info->lst_hyper));
- _DtCvSetJoinInfo(lay_info, False, -1);
- /*
- * If we had to do a bigger segment,
- * then we're done processing the target segment.
- */
- if (stringLen == _DtCvStrLen(pChar,_DtCvIsSegWideChar(cur_seg)))
- {
- if (_DtCvCheckLineSyntax (canvas, cur_seg,
- *cur_start, stringLen, False) == False)
- _DtCvSetJoinInfo(lay_info, True, -1);
- else if (_DtCvIsSegNewLine (cur_seg)) {
- _DtCvSaveInfo (canvas, lay_info, max_width,
- r_margin, txt_justify);
- while (lay_info->delayed_search_saves > 0) {
- _DtCvSetSearchEntryInfo(canvas,
- canvas->txt_cnt - 1);
- lay_info->delayed_search_saves--;
- }
- }
- return 0;
- }
- *cur_start = retStart;
- }
- else if (spaceSize)
- {
- /*
- * If a space was included as the last character,
- * remove it now.
- */
- lay_info->line_bytes--;
- lay_info->cur_len -= spaceSize;
- }
- /*
- * Save the information
- */
- _DtCvSaveInfo (canvas, lay_info, max_width, r_margin, txt_justify);
- if (*cur_start == 0 && (cur_seg->type & _DtCvSEARCH_FLAG))
- lay_info->delayed_search_saves--;
- while (lay_info->delayed_search_saves > 0) {
- _DtCvSetSearchEntryInfo(canvas, canvas->txt_cnt - 1);
- lay_info->delayed_search_saves--;
- }
- /*
- * Skip the spaces.
- */
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(cur_seg),
- _DtCvIsSegWideChar(cur_seg),
- *cur_start);
- if (_DtCvIsSegWideChar(cur_seg))
- {
- wcp = pChar;
- while (' ' == *wcp)
- {
- wcp++;
- (*cur_start)++;
- }
- pChar = wcp;
- }
- else /* single byte string */
- {
- strPtr = pChar;
- while (' ' == *strPtr)
- {
- strPtr++;
- (*cur_start)++;
- }
- pChar = strPtr;
- }
- /*
- * are we at the end of the segment?
- */
- if ((_DtCvIsSegWideChar(cur_seg) && 0 == *((wchar_t *) pChar))
- ||
- (_DtCvIsSegRegChar(cur_seg) && 0 == *((char *) pChar)))
- return 0;
- if (*cur_start == 0 && (cur_seg->type & _DtCvSEARCH_FLAG))
- lay_info->delayed_search_saves++;
- /*
- * Initialize the global variables
- */
- lay_info->line_seg = cur_seg;
- lay_info->line_start = *cur_start;
- lay_info->text_x_pos = l_margin;
- if (CheckFormat(lay_info) == True)
- return 1;
- /*
- * check to see if this a hypertext that needs
- * to be remembered.
- */
- _DtCvCheckAddHyperToTravList (canvas, cur_seg, _DtCvTRUE,
- &(lay_info->lst_vis),
- &(lay_info->lst_hyper),
- &(lay_info->cur_len));
- }
- }
- else if (_DtCvIsSegNewLine (cur_seg))
- {
- /*
- * Force a save - even if it is an empty line.
- */
- _DtCvSaveInfo (canvas, lay_info, max_width, r_margin, txt_justify);
- while (lay_info->delayed_search_saves > 0) {
- _DtCvSetSearchEntryInfo(canvas, canvas->txt_cnt - 1);
- lay_info->delayed_search_saves--;
- }
- }
- return 0;
- } /* End _DtCvProcessStringSegment */
- /******************************************************************************
- * Function: _DtCvSetJoinInfo
- *
- * Returns: sets the joining information to the given information.
- *
- *****************************************************************************/
- void
- _DtCvSetJoinInfo (
- _DtCvLayoutInfo *lay_info,
- _DtCvValue flag,
- int txt_ln)
- {
- lay_info->join = flag;
- lay_info->join_line = txt_ln;
- }
- /******************************************************************************
- * Function: _DtCvGetNextTravEntry
- *
- * Returns: >= 0 if success,
- * -1 if failure.
- *
- * Purpose: Return the next available entry in the traversal list.
- *
- *****************************************************************************/
- int
- _DtCvGetNextTravEntry (
- _DtCanvasStruct *canvas)
- {
- int nxtEntry = canvas->trav_cnt;
- /*
- * does the list need to grow?
- */
- if (nxtEntry >= canvas->trav_max)
- {
- /*
- * grow by a set amount
- */
- canvas->trav_max += GROW_SIZE;
- /*
- * realloc or malloc?
- */
- if (NULL != canvas->trav_lst)
- canvas->trav_lst = (_DtCvTraversalInfo *) realloc (
- (char *) canvas->trav_lst,
- ((sizeof(_DtCvTraversalInfo)) * canvas->trav_max));
- else
- canvas->trav_lst = (_DtCvTraversalInfo *) malloc (
- ((sizeof(_DtCvTraversalInfo)) * canvas->trav_max));
- /*
- * did the memory allocation work? if not return error code.
- */
- if (NULL == canvas->trav_lst)
- {
- canvas->trav_max = 0;
- canvas->trav_cnt = 0;
- nxtEntry = -1;
- }
- }
- canvas->trav_lst[nxtEntry] = DefTravData;
- return nxtEntry;
- }
- /******************************************************************************
- * Function: _DtCvSetTravEntryInfo
- *
- * Returns: 0 if success,
- * -1 if failure.
- *
- * Purpose: Set the high level information in an entry of the traversal
- * list.
- *****************************************************************************/
- int
- _DtCvSetTravEntryInfo (
- _DtCanvasStruct *canvas,
- int entry,
- _DtCvTraversalType type,
- _DtCvSegmentI *p_seg,
- int line_idx,
- _DtCvValue inc)
- {
- int result = -1;
- if (-1 != entry && entry <= canvas->trav_cnt)
- {
- _DtCvTraversalInfo *travEntry = &(canvas->trav_lst[entry]);
- travEntry->type = type;
- travEntry->seg_ptr = p_seg;
- travEntry->idx = line_idx;
- if (_DtCvTRUE == inc)
- canvas->trav_cnt++;
- result = 0;
- }
- return result;
- }
- int
- _DtCvGetNextSearchEntry(_DtCanvasStruct* canvas)
- {
- if (canvas->search_cnt >= canvas->search_max) {
- canvas->search_max += GROW_SIZE;
- if (canvas->searchs)
- canvas->searchs = (_DtCvSearchData *)
- realloc((void*)canvas->searchs,
- canvas->search_max * sizeof(_DtCvSearchData));
- else
- canvas->searchs = (_DtCvSearchData *)
- malloc(canvas->search_max * sizeof(_DtCvSearchData));
- }
- canvas->searchs[canvas->search_cnt].idx = -1;
- return canvas->search_cnt++;
- }
- int
- _DtCvSetSearchEntryInfo(_DtCanvasStruct* canvas, int line_idx)
- {
- int search_idx;
- /* get a next available slot for search */
- search_idx = _DtCvGetNextSearchEntry(canvas);
- /* save information (i.e. line_idx) */
- canvas->searchs[search_idx].idx = line_idx;
- }
- /******************************************************************************
- * Function: _DtCvSetTravEntryPos
- *
- * Returns: 0 if success,
- * -1 if failure.
- *
- * Purpose: Set the position and dimension information of an entry in
- * the traversal list.
- *
- *****************************************************************************/
- int
- _DtCvSetTravEntryPos (
- _DtCanvasStruct *canvas,
- int entry,
- _DtCvUnit x,
- _DtCvUnit y,
- _DtCvUnit width,
- _DtCvUnit height)
- {
- int result = -1;
- if (-1 != entry && entry <= canvas->trav_cnt)
- {
- _DtCvTraversalInfo *travEntry = &(canvas->trav_lst[entry]);
- travEntry->x_pos = x;
- travEntry->y_pos = y;
- travEntry->width = width;
- travEntry->height = height;
- result = 0;
- }
- return result;
- }
- /******************************************************************************
- * Function: _DtCvCalcMarkPos
- *
- * Returns: 0 if success,
- * -1 if failure.
- *
- * Purpose: Calcalate the position and dimension information of a mark.
- *
- *****************************************************************************/
- int
- _DtCvCalcMarkPos (
- _DtCanvasStruct *canvas,
- int entry,
- _DtCvUnit *ret_x,
- _DtCvUnit *ret_y,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_height)
- {
- int result = -1;
- if (-1 != entry && entry <= canvas->mark_cnt)
- {
- _DtCvMarkData *mark = &(canvas->marks[entry]);
- /*
- * if we've got a line index for the mark, get the positions.
- */
- if (-1 != mark->beg.line_idx && -1 != mark->end.line_idx)
- {
- _DtCvDspLine *line = &(canvas->txt_lst[mark->beg.line_idx]);
- *ret_x = mark->beg.x;
- *ret_y = mark->beg.y - line->ascent;
- if (mark->beg.line_idx == mark->end.line_idx)
- *ret_width = mark->end.x - *ret_x;
- else
- *ret_width = canvas->txt_lst[mark->beg.line_idx].max_x - *ret_x;
- *ret_height = line->ascent + line->descent + 1;
- result = 0;
- }
- }
- return result;
- }
- /******************************************************************************
- * Function: _DtCvSortTraversalList
- *
- * Returns: nothing
- *
- * Purpose: Sort the traversal list
- *
- *****************************************************************************/
- void
- _DtCvSortTraversalList (
- _DtCanvasStruct *canvas,
- _DtCvValue retain)
- {
- int curTrav = canvas->cur_trav;
- if (1 < canvas->trav_cnt)
- {
- /*
- * indicate this is the current traversal
- */
- if (-1 != curTrav)
- canvas->trav_lst[curTrav].active = retain;
- /*
- * sort the items.
- */
- qsort (canvas->trav_lst, canvas->trav_cnt, sizeof(_DtCvTraversalInfo),
- CompareTraversalPos);
- if (_DtCvTRUE == retain && -1 != curTrav &&
- _DtCvFALSE == canvas->trav_lst[curTrav].active)
- {
- curTrav = 0;
- while (_DtCvFALSE == canvas->trav_lst[curTrav].active)
- curTrav++;
- canvas->cur_trav = curTrav;
- }
- /*
- * clear the active flag
- */
- if (-1 != curTrav)
- canvas->trav_lst[curTrav].active = _DtCvFALSE;
- }
- }
- /*****************************************************************************
- * Function: _DtCvCvtSegsToPts()
- *
- * Purpose: Given a set of segments, determine the ending points.
- *
- *****************************************************************************/
- _DtCvStatus
- _DtCvCvtSegsToPts (
- _DtCanvasStruct *canvas,
- _DtCvSegPtsI **segs,
- _DtCvSelectData *beg,
- _DtCvSelectData *end,
- _DtCvUnit *ret_y1,
- _DtCvUnit *ret_y2,
- _DtCvSegmentI **ret_seg)
- {
- int count;
- int cnt;
- int start;
- int length;
- long lineIdx;
- int linkIdx = -1;
- _DtCvValue lastVisLnk = _DtCvFALSE;
- _DtCvUnit minY = -1;
- _DtCvUnit maxY = 0;
- _DtCvUnit startX;
- _DtCvUnit endX;
- _DtCvUnit segWidth;
- _DtCvSegmentI *pSeg;
- _DtCvSegmentI *saveSeg;
- _DtCvSegmentI **retSeg;
- _DtCvDspLine *lines = canvas->txt_lst;
- _DtCvFlags result = _DtCvSTATUS_NONE;
- _DtCvSelectData *tmpBeg;
- _DtCvSelectData *tmpEnd;
- _DtCvSelectData bReg;
- _DtCvSelectData eReg;
- /*
- * initialize the structures.
- */
- bReg = DefSelectData;
- eReg = DefSelectData;
- *beg = DefSelectData;
- *end = DefSelectData;
- /*
- * go through each segment and determine the starting positions.
- */
- while (NULL != *segs)
- {
- result = _DtCvSTATUS_OK;
- /*
- * what line is this segment on?
- */
- lineIdx = (long) ((*segs)->segment->internal_use);
- /*
- * get some information about the line
- */
- length = lines[lineIdx].length;
- start = lines[lineIdx].byte_index;
- startX = _DtCvGetStartXOfLine(&(lines[lineIdx]), &pSeg);
- pSeg = lines[lineIdx].seg_ptr;
- /*
- * now skip the segments on this line that aren't in the data pt.
- */
- while (NULL != pSeg && pSeg != (*segs)->segment)
- {
- /*
- * advance past any hypertext link offsets.
- */
- startX = _DtCvAdvanceXOfLine(canvas, pSeg, startX,
- &linkIdx, &lastVisLnk);
- /*
- * we know that this is not the segment we are looking for,
- * so go past it.
- */
- _DtCvGetWidthOfSegment(canvas, pSeg, start, length,
- &cnt, &segWidth, NULL);
- /*
- * skip the segment's width, decrease the overall length by
- * the segment's count, reset the character start point and
- * go to the next segment.
- */
- startX += segWidth;
- length -= cnt;
- start = 0;
- pSeg = pSeg->next_disp;
- }
- /*
- * This segment should be all or partially selected.
- */
- if (NULL == pSeg)
- return _DtCvSTATUS_BAD;
- /*
- * now figure the start location.
- */
- startX = _DtCvAdvanceXOfLine(canvas, pSeg, startX,
- &linkIdx, &lastVisLnk);
- /*
- * guarenteed that this is the *first* line that the segment
- * exists on. Therefore, may have to go to another line for
- * the correct offset
- */
- while (start + length < (*segs)->offset)
- {
- do { lineIdx++; } while (lineIdx < canvas->txt_cnt
- && pSeg != lines[lineIdx].seg_ptr);
- if (lineIdx >= canvas->txt_cnt)
- return _DtCvSTATUS_BAD;
- length = lines[lineIdx].length;
- start = lines[lineIdx].byte_index;
- startX = lines[lineIdx].text_x;
- linkIdx = -1;
- lastVisLnk = False;
- startX = _DtCvAdvanceXOfLine(canvas, pSeg, startX,
- &linkIdx, &lastVisLnk);
- }
- /*
- * how many characters do we need to skip?
- */
- count = (*segs)->offset - start;
- segWidth = 0;
- if (0 < count)
- _DtCvGetWidthOfSegment(canvas, pSeg, start, count,
- &cnt, &segWidth, NULL);
- /*
- * adjust the info by the width of the skipped characters.
- */
- start += count;
- length -= count;
- startX += segWidth;
- /*
- * is this a region? If so set the region information instead.
- */
- tmpBeg = beg;
- tmpEnd = end;
- retSeg = ret_seg;
- if (_DtCvIsSegRegion((*segs)->segment))
- {
- tmpBeg = &bReg;
- tmpEnd = &eReg;
- retSeg = &saveSeg;
- }
- /*
- * does this segment start the selection? text or region?
- */
- if (tmpBeg->x == -1 || tmpBeg->y > lines[lineIdx].baseline ||
- (tmpBeg->line_idx == lineIdx && tmpBeg->x > startX))
- {
- tmpBeg->x = startX;
- tmpBeg->y = lines[lineIdx].baseline;
- tmpBeg->line_idx = lineIdx;
- tmpBeg->char_idx = lines[lineIdx].length - length;
- if (NULL != retSeg)
- *retSeg = (*segs)->segment;
- }
- /*
- * get the amount of this segment that is selected.
- */
- count = (*segs)->len;
- /*
- * is it longer than what's (left) on this line?
- */
- while (count > length)
- {
- /*
- * go to the next line containing the segment
- */
- do {
- /*
- * does this line have the minium y?
- */
- if (minY == -1 ||
- minY > lines[lineIdx].baseline - lines[lineIdx].ascent)
- minY = lines[lineIdx].baseline - lines[lineIdx].ascent;
- lineIdx++;
- } while (lineIdx < canvas->txt_cnt
- && pSeg != lines[lineIdx].seg_ptr);
- /*
- * did we run out of lines?
- */
- if (lineIdx >= canvas->txt_cnt)
- return _DtCvSTATUS_BAD;
-
- /*
- * start over on this line
- */
- segWidth = 0;
- /*
- * get the true count to the next offset
- */
- cnt = lines[lineIdx].byte_index - start;
- /*
- * get the next lines starting info.
- */
- start = lines[lineIdx].byte_index;
- length = lines[lineIdx].length;
- startX = _DtCvGetStartXOfLine(&(lines[lineIdx]), &pSeg);
- linkIdx = -1;
- lastVisLnk = False;
- startX = _DtCvAdvanceXOfLine(canvas, pSeg, startX,
- &linkIdx, &lastVisLnk);
- /*
- * subtract the previous length
- */
- count -= cnt;
- }
- /*
- * now go down the line, examining each segment.
- */
- while (0 < count)
- {
- /*
- * findout how many characters are in the next segment, and its
- * width.
- */
- _DtCvGetWidthOfSegment(canvas,pSeg,start,count,&cnt,&segWidth,NULL);
- /*
- * there are less than in the count, go to the next segment.
- */
- if (cnt < count)
- {
- pSeg = pSeg->next_disp;
- start = 0;
- startX += segWidth;
- }
- length -= cnt;
- count -= cnt;
- }
- endX = startX + segWidth;
- /*
- * does this segment end a segment?
- */
- if (tmpEnd->x == -1 || tmpEnd->y < lines[lineIdx].baseline ||
- (tmpEnd->line_idx == lineIdx && tmpEnd->x < endX))
- {
- tmpEnd->x = endX;
- tmpEnd->y = lines[lineIdx].baseline;
- tmpEnd->line_idx = lineIdx;
- tmpEnd->char_idx = lines[lineIdx].length - length;
- }
- /*
- * check for min and max values
- */
- if (minY == -1 ||
- minY > lines[lineIdx].baseline - lines[lineIdx].ascent)
- minY = lines[lineIdx].baseline - lines[lineIdx].ascent;
- if (maxY < lines[lineIdx].baseline + lines[lineIdx].descent)
- maxY = lines[lineIdx].baseline + lines[lineIdx].descent;
- /*
- * go to the next segment
- */
- segs++;
- }
- /*
- * now determine if a region really starts the beginning of a
- * selection or a text does.
- *
- * was a region found?
- */
- if (-1 != bReg.x)
- {
- /*
- * if no text was found, take the region information.
- */
- if (-1 == beg->x)
- {
- *beg = bReg;
- if (NULL != ret_seg)
- *ret_seg = saveSeg;
- }
- /*
- * or if the region is inline to the other
- * text and it is before the text, then take it's x value.
- */
- else if (bReg.x < beg->x &&
- (bReg.line_idx == beg->line_idx ||
- /*
- * Or if the region is 'standalone' (a bullet of a list, a
- * graphic to wrap around, etc.) then check to see if it
- * straddles the other information and is before the text. If
- * it does, take it's x value.
- */
- _DtCvStraddlesPt(beg->y,
- bReg.y - lines[bReg.line_idx].ascent,
- bReg.y - lines[bReg.line_idx].descent)))
- {
- beg->x = bReg.x;
- if (NULL != ret_seg)
- *ret_seg = saveSeg;
- }
- }
- /*
- * now determine if a region really ends the selection or a text does.
- *
- * was a region found?
- */
- if (-1 != eReg.x)
- {
- /*
- * if no text was found, take the region information.
- */
- if (-1 == end->x)
- *end = eReg;
- /*
- * or if the region is inline to the other
- * text and it is before the text, then take it's x value.
- */
- else if (eReg.x > end->x &&
- (eReg.line_idx == end->line_idx ||
- /*
- * Or if the region is 'standalone' (a bullet of a list, a
- * graphic to wrap around, etc.) then check to see if it
- * straddles the other information and is before the text. If
- * it does, take it's x value.
- */
- _DtCvStraddlesPt(end->y,
- eReg.y - lines[eReg.line_idx].ascent,
- eReg.y - lines[eReg.line_idx].descent)))
- end->x = eReg.x;
- }
- if (NULL != ret_y1)
- *ret_y1 = minY;
- if (NULL != ret_y2)
- *ret_y2 = maxY;
- return result;
- }
- /*****************************************************************************
- * Function: _DtCvAddToMarkList()
- *
- * Purpose: Add a mark to the list of marks.
- *
- *****************************************************************************/
- int
- _DtCvAddToMarkList (
- _DtCanvasStruct *canvas,
- _DtCvPointer client_data,
- _DtCvValue flag,
- _DtCvSelectData *beg,
- _DtCvSelectData *end)
- {
- _DtCvMarkData *nxtMark;
- /*
- * does the array need more memory?
- */
- if (canvas->mark_cnt >= canvas->mark_max)
- {
- canvas->mark_max += GROW_SIZE;
- if (NULL == canvas->marks)
- canvas->marks = (_DtCvMarkData *) malloc(
- sizeof(_DtCvMarkData) * canvas->mark_max);
- else
- canvas->marks = (_DtCvMarkData *) realloc((void *) canvas->marks,
- sizeof(_DtCvMarkData) * canvas->mark_max);
- /*
- * memory loss - bail
- */
- if (NULL == canvas->marks)
- return -1;
- }
- /*
- * set the mark information
- */
- nxtMark = &(canvas->marks[canvas->mark_cnt]);
- nxtMark->on = flag;
- nxtMark->client_data = client_data;
- nxtMark->beg = *beg;
- nxtMark->end = *end;
- canvas->mark_cnt++;
- return (canvas->mark_cnt - 1);
- }
|