1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380 |
- /*
- * 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 || canvas->mb_length > 1) &&
- 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 || canvas->mb_length > 1)
- && 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) || canvas->mb_length > 1)
- {
- /*
- * 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 mbl;
- 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 && canvas->mb_length == 1)
- {
- 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)
- {
- if (wcFlag) len++;
- else
- {
- mbl = mblen(pChar + len, MB_CUR_MAX);
- if (mbl == -1)
- {
- ++len;
- continue;
- }
- else if (!mbl) break;
- else len += mbl;
- }
- 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++;
- }
- void
- _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);
- }
|