1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695 |
- /*
- * 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 librararies and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: Layout.c /main/31 1996/10/25 12:00:15 cde-hp $ */
- /************************************<+>*************************************
- ****************************************************************************
- **
- ** File: Layout.c
- **
- ** Project: CDE Info System
- **
- ** Description: Lays out the information on a canvas.
- **
- ** (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 <stdio.h>
- #include <string.h>
- #include <limits.h>
- /*
- * Canvas Engine includes
- */
- #include "CanvasP.h"
- #include "CanvasSegP.h"
- /*
- * private includes
- */
- #include "bufioI.h"
- #include "CanvasI.h"
- #include "CvStringI.h"
- #include "LayoutUtilI.h"
- #include "SelectionI.h"
- #include "VirtFuncsI.h"
- #ifdef NLS16
- #include <nl_types.h>
- #endif
- /******************************************************************************
- *
- * Private Macros
- *
- *****************************************************************************/
- #define ObjHorizOrient(x) (_DtCvContainerOrientOfSeg(x))
- #define ObjVertOrient(x) (_DtCvContainerVOrientOfSeg(x))
- #define TxtHorizJustify(x) (_DtCvContainerJustifyOfSeg(x))
- #define TxtVertJustify(x) (_DtCvContainerVJustifyOfSeg(x))
- #define Border(x) (_DtCvContainerBorderOfSeg(x))
- #define BrdWidth(x) (_DtCvContainerLineWidthOfSeg(x))
- #define BrdData(x) (_DtCvContainerLineDataOfSeg(x))
- #define NotJoining(x) (False == (x)->info.join)
- #define JoinSet(x) (True == (x)->info.join)
- #define CheckAddToHyperList(a, b) \
- _DtCvCheckAddHyperToTravList(a, b, _DtCvTRUE, \
- &(layout->info.lst_vis), \
- &(layout->info.lst_hyper), &(layout->info.cur_len))
- /*****************************************************************************
- * Private Defines
- *****************************************************************************/
- /*
- * Defines for the dimension arrays
- */
- #define DIMS_LEFT 0
- #define DIMS_RIGHT 1
- #define DIMS_LM 0
- #define DIMS_CENTER 1
- #define DIMS_RM 2
- #define DIMS_TOP 0
- #define DIMS_BOTTOM 2
- #define DIMS_WIDTH 0
- #define DIMS_HEIGHT 1
- #define DIMS_YPOS 1
- #define DIMS_TC 0
- #define DIMS_BC 1
- /*
- */
- #define GROW_SIZE 10
- /******************************************************************************
- *
- * Private typedefs
- *
- *****************************************************************************/
- /*
- * top/bottom dimension array
- * -------------------------------------------
- * / DIMS_HEIGHT / DIMS_HEIGHT / DIMS_HEIGHT /|
- * / DIMS_YPOS / DIMS_YPOS / DIMS_YPOS / |
- * /-------------/-------------/-------------/ |
- * / DIMS_WIDTH / DIMS_WIDTH / DIMS_WIDTH /| /|
- * --------------|-------------|-------------| |/ |
- * DIMS_TOP | DIMS_LM | DIMS_CENTER | DIMS_RM | | /|
- * |-------------|-------------|-------------|/|/ |
- * unused | | | | | /
- * |-------------|-------------|-------------|/|/
- * DIMS_BOTTOM | DIMS_LM | DIMS_CENTER | DIMS_RM | /
- * ------------------------------------------|/
- */
- typedef _DtCvUnit TopDims[DIMS_BOTTOM+1][DIMS_RM+1][DIMS_HEIGHT+1];
- /*
- * left/right side dimension array - contains only the height or y_pos.
- * ----------------------------
- * DIMS_TOP | DIMS_LEFT | DIMS_RIGHT |
- * |------------|-------------|
- * DIMS_CENTER | DIMS_LEFT | DIMS_RIGHT |
- * |------------|-------------|
- * DIMS_BOTTOM | DIMS_LEFT | DIMS_RIGHT |
- * ----------------------------
- */
- typedef _DtCvUnit SideDims[DIMS_BOTTOM+1][DIMS_RIGHT+1];
- /*
- * corner dimension array - contains only the height or y_pos.
- * ----------------------------
- * DIMS_TC | DIMS_LEFT | DIMS_RIGHT |
- * |------------|-------------|
- * DIMS_BC | DIMS_LEFT | DIMS_RIGHT |
- * ----------------------------
- */
- typedef _DtCvUnit CornerDims[DIMS_BC+1][DIMS_RIGHT+1];
- /*
- * flow dimension array
- * -------------|--------------
- * DIMS_LEFT | DIMS_WIDTH | DIMS_HEIGHT |
- * | | DIMS_YPOS |
- * |------------|-------------|
- * DIMS_RIGHT | DIMS_WIDTH | DIMS_HEIGHT |
- * | | DIMS_YPOS |
- * ----------------------------
- */
- typedef _DtCvUnit FlowDims[DIMS_RIGHT+1][DIMS_HEIGHT+1];
- /*
- * margin data - important for determining flowing
- */
- typedef struct _dataPoint {
- _DtCvUnit left;
- _DtCvUnit right;
- _DtCvUnit y_pos;
- _DtCvUnit x_units;
- struct _dataPoint *next_pt;
- } DataPoint;
- /*
- * count information
- */
- typedef struct _cntInfo {
- int beg_txt;
- int end_txt;
- int beg_ln;
- int end_ln;
- int my_lines;
- int beg_brk;
- int end_brk;
- } CntInfo;
- /*
- * group information
- */
- typedef struct _grpInfo {
- _DtCvUnit min_x;
- _DtCvUnit max_x;
- _DtCvUnit top_y;
- _DtCvUnit bot_y;
- CntInfo cnt;
- struct _grpInfo *next_info;
- } GrpInfo;
- /*
- * layout information per container
- */
- typedef struct _layFrmtInfo {
- _DtCvUnit height;
- _DtCvUnit width;
- CntInfo cnt;
- struct _layFrmtInfo *next_info;
- } LayFrmtInfo;
- /*
- * the layout information carried around
- */
- typedef struct _layoutInfo {
- _DtCvUnit max_width; /* the current max width */
- _DtCvUnit id_Ypos; /* the y coordinate of the id found. */
- _DtCvUnit left; /* the current left margin for the
- current active container (incl br)*/
- _DtCvUnit right; /* the current right margin for the
- current active container (incl br)*/
- _DtCvUnit first; /* the current first indent */
- _DtCvUnit lmargin; /* the current absolute left margin */
- _DtCvUnit rmargin; /* the current absolute right margin */
- _DtCvUnit divisor; /* the current margin divisor */
- _DtCvUnit string_end;
- _DtCvUnit sub_end;
- _DtCvUnit super_end;
- _DtCvValue id_found; /* indicates if the id has been found*/
- _DtCvValue super_script;
- _DtCvValue sub_script;
- _DtCvValue stat_flag;
- _DtCvValue margin_non_zero;
- _DtCvValue brdr_flag; /* within container with a border */
- _DtCvValue table_flag; /* within table */
- _DtCvFrmtOption txt_justify;
- unsigned int cur_start; /* offset into the current segment
- to process */
- _DtCvSegmentI *lst_rendered; /* indicates the last string/region */
- char *target_id; /* if non-null, the id to search for */
- DataPoint *data_pts;
- GrpInfo *grp_lst; /* list of groups */
- _DtCvLayoutInfo info;
- } LayoutInfo;
- /*
- * information for laying out cells in a table.
- */
- typedef struct {
- int col_spn;
- int row_spn;
- _DtCvUnit pos_x;
- LayFrmtInfo info;
- _DtCvSegmentI *cell_seg;
- } CellInfo;
- /*
- * column description information for a table.
- */
- typedef struct _columnSpec {
- _DtCvUnit min;
- _DtCvUnit max;
- _DtCvUnit actual;
- _DtCvValue hanger;
- _DtCvFrmtOption justify;
- } ColumnSpec;
- /*
- * row description information
- */
- typedef struct _rowSpec {
- int column;
- _DtCvUnit y_adj;
- _DtCvUnit height;
- _DtCvUnit lst_height;
- char *next_id;
- } RowSpec;
- /*****************************************************************************
- * Private Variables/Data
- *****************************************************************************/
- static const LayFrmtInfo DefLayFrmtInfo = { 0, 0, {-1, -1, -1, -1, 0}, NULL };
- static const GrpInfo DefGrpInfo = { 0, 0, 0, 0, {-1, -1, -1, -1, 0}};
- static const LayoutInfo DefInfo = {
- 0, /* _DtCvUnit max_width; */
- 0, /* _DtCvUnit id_Ypos; */
- 0, /* _DtCvUnit left; */
- 0, /* _DtCvUnit right; */
- 0, /* _DtCvUnit first; */
- 0, /* _DtCvUnit lmargin; */
- 0, /* _DtCvUnit rmargin; */
- 1, /* _DtCvUnit divisor; */
- 0, /* _DtCvUnit string_end; */
- 0, /* _DtCvUnit sub_end; */
- 0, /* _DtCvUnit super_end; */
- False, /* _DtCvValue id_found; */
- False, /* _DtCvValue super_script; */
- False, /* _DtCvValue sub_script; */
- False, /* _DtCvValue stat_flag; */
- False, /* _DtCvValue margin_non_zero; */
- False, /* _DtCvValue brdr_flag; */
- False, /* _DtCvValue table_flag; */
- _DtCvJUSTIFY_LEFT, /* _DtCvFrmtOption txt_justify; */
- 0, /* unsigned int cur_start; */
- NULL, /* _DtCvSegmentI *lst_rendered; */
- NULL, /* char *target_id; */
- NULL, /* DataPoint *data_pts; */
- NULL, /* GrpInfo *data_pts; */
- };
- static const DataPoint DefDataPt = { 0, 0, _CEFORMAT_ALL, 0, NULL};
- static const double HeadDivisor = 10000.0;
- static const char *PeriodStr = ".";
- static const char *DefWidth[2] = { "", NULL };
- static const _DtCvSegmentI BlankTableCell =
- {
- _DtCvCONTAINER, /* type */
- -1, /* link_idx */
- { /* container info */
- NULL, /* id */
- NULL, /* justify_char */
- _DtCvDYNAMIC, /* type */
- _DtCvBORDER_NONE, /* border */
- _DtCvJUSTIFY_LEFT, /* justify */
- _DtCvJUSTIFY_TOP, /* vjustify */
- _DtCvJUSTIFY_LEFT, /* orient */
- _DtCvJUSTIFY_TOP, /* vorient */
- _DtCvWRAP_NONE, /* flow */
- 0, /* percent */
- 0, /* leading */
- 0, /* fmargin */
- 0, /* lmargin */
- 0, /* rmargin */
- 0, /* tmargin */
- 0, /* bmargin */
- _DtCvBORDER_NONE, /* bdr_info */
- NULL /* seg_list */
- },
- NULL, /* next_seg */
- NULL, /* next_disp */
- NULL, /* client_use */
- NULL /* internal_use */
- };
- /*****************************************************************************
- * Private Function Declarations
- *****************************************************************************/
- static void AdjustForBorders(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvFrmtOption brdr,
- _DtCvUnit line_width,
- _DtCvUnit *ret_bot,
- _DtCvUnit *ret_right);
- static void AdjustHeadPosition(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *p_seg,
- TopDims *top_bot,
- SideDims *side,
- CornerDims *corner,
- FlowDims *flow,
- LayFrmtInfo *info,
- _DtCvUnit base_y,
- _DtCvUnit base_left,
- _DtCvUnit block_width,
- _DtCvUnit left_margin,
- _DtCvUnit right_margin);
- static void AdjustObjectPosition(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvFrmtOption justify,
- int start_txt,
- int start_ln,
- int start_brk,
- int end_txt,
- int end_ln,
- int end_brk,
- int brdr_cnt,
- _DtCvUnit height_adj,
- _DtCvUnit x_adj,
- _DtCvUnit y_adj,
- _DtCvUnit internal_y);
- static void CheckSaveInfo (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *new_seg,
- int start);
- static void DetermineFlowConstraints(
- LayoutInfo *layout,
- FlowDims flow_dims,
- _DtCvUnit left_margin,
- _DtCvUnit right_margin,
- _DtCvUnit start_y,
- DataPoint *left_pt,
- DataPoint *right_pt);
- static void DetermineHeadPositioning(
- TopDims *top_bot,
- SideDims *side,
- CornerDims *corner,
- FlowDims *flow,
- _DtCvUnit start_y,
- _DtCvUnit max_top,
- _DtCvUnit block_size,
- _DtCvUnit *ret_side_size);
- static void DetermineMaxDims(
- TopDims *top_bot,
- CornerDims *corner,
- _DtCvUnit left_margin,
- _DtCvUnit right_margin,
- _DtCvUnit *top_height,
- _DtCvUnit *bot_height,
- _DtCvUnit *max_width);
- static int DrawBorders(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvFrmtOption brdr,
- _DtCvPointer data,
- _DtCvUnit line_width,
- _DtCvUnit top_y,
- _DtCvUnit bot_y,
- _DtCvUnit left_x,
- _DtCvUnit right_x);
- static void FormatCell(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *cell_seg,
- _DtCvUnit span_width,
- _DtCvUnit min_height,
- DataPoint base_pt,
- int *ret_ln,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_height,
- _DtCvValue *ret_tab_flag);
- static void InitDimArrays(
- TopDims *top_bot,
- SideDims *side,
- CornerDims *corner,
- FlowDims *flow);
- static _DtCvStatus LayoutCanvasInfo (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvUnit divisor,
- char *target_id);
- static _DtCvValue LinesMayChange(
- _DtCanvasStruct *canvas,
- int start_ln,
- int end_ln,
- int brdr_cnt);
- static _DtCvUnit MoveGroup (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- GrpInfo *tst_grp,
- _DtCvUnit needed);
- static _DtCvUnit MoveLines (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- int idx,
- _DtCvUnit top_y,
- _DtCvUnit bot_y,
- _DtCvUnit needed);
- static _DtCvUnit MoveText (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- int idx,
- _DtCvUnit top_y,
- _DtCvUnit bot_y,
- _DtCvUnit needed);
- static void ProcessContainer(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *con_seg,
- _DtCvUnit min_y,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_max_x,
- int *ret_cnt);
- static void ProcessSegmentList(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *cur_seg,
- _DtCvUnit min_y,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_max_x,
- int **ret_vert);
- /******************************************************************************
- *
- * Private Functions
- *
- *****************************************************************************/
- /******************************************************************************
- * Function: AdjustTextPositions
- *
- * changes the baseline and text_x positioning of the text line by the
- * offsets indicated.
- *****************************************************************************/
- static void
- AdjustTextPositions(
- _DtCanvasStruct *canvas,
- int beg,
- int end,
- _DtCvUnit x_offset,
- _DtCvUnit y_offset)
- {
- if ( 0 != y_offset || 0 != x_offset)
- {
- while (beg < end)
- {
- canvas->txt_lst[beg].baseline += y_offset;
- canvas->txt_lst[beg].text_x += x_offset;
- beg++;
- }
- }
- }
- /******************************************************************************
- * Function: AdjustLinePositions
- *
- * changes the x & positions and the max x & y values by the offsets indicated.
- *****************************************************************************/
- static void
- AdjustLinePositions(
- _DtCanvasStruct *canvas,
- int beg,
- int end,
- _DtCvUnit x_offset,
- _DtCvUnit y_offset)
- {
- if ( 0 != y_offset || 0 != x_offset)
- {
- while (beg < end)
- {
- canvas->line_lst[beg].pos_y += y_offset;
- canvas->line_lst[beg].max_y += y_offset;
- canvas->line_lst[beg].pos_x += x_offset;
- canvas->line_lst[beg].max_x += x_offset;
- beg++;
- }
- }
- }
- /******************************************************************************
- * Function: AdjustPgBrk
- *
- * changes the y position of a page break.
- *****************************************************************************/
- static void
- AdjustPgBrk(
- _DtCanvasStruct *canvas,
- int beg,
- int end,
- _DtCvUnit y_offset)
- {
- if (0 != y_offset)
- {
- while (beg < end)
- canvas->pg_breaks[beg++] += y_offset;
- }
- }
- /******************************************************************************
- * Function: MaxXOfLine
- *
- * MaxXOfLine determines the max X of a line segment.
- *
- *****************************************************************************/
- /******************************************************************************
- * Function: MaxXOfLine
- *
- * MaxXOfLine determines the max X of a line segment.
- *
- *****************************************************************************/
- static _DtCvUnit
- MaxXOfLine(
- _DtCanvasStruct *canvas,
- _DtCvDspLine *line)
- {
- _DtCvValue lastLinkVisible = FALSE;
- int count = line->length;
- int start = line->byte_index;
- int len;
- int lnkInd = -1;
- _DtCvUnit xPos;
- _DtCvUnit tmpWidth;
- _DtCvSegmentI *pSeg;
- xPos = _DtCvGetStartXOfLine(line, &pSeg);
- while (pSeg != NULL && count > 0)
- {
- xPos = _DtCvAdvanceXOfLine(canvas, pSeg, xPos,
- &lnkInd, &lastLinkVisible);
- _DtCvGetWidthOfSegment(canvas, pSeg, start, count,
- &len, &tmpWidth, NULL);
- xPos += tmpWidth;
- count -= len;
- start = 0;
- pSeg = pSeg->next_disp;
- }
- return xPos;
- } /* End MaxXOfLine */
- /*****************************************************************************
- * Function: void GetLinkInfo ()
- *
- * Parameters:
- * canvas Specifies the handle for the canvas.
- *
- * Returns: A handle to the canvas or NULL if an error occurs.
- *
- * Purpose:
- *
- *****************************************************************************/
- static _DtCvValue
- GetLinkInfo (
- _DtCvHandle canvas_handle,
- int indx,
- _DtCvUnit *ret_x,
- _DtCvUnit *ret_y,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_height)
- {
- int len;
- int line;
- int count;
- int startChar;
- int lnkIndx = -1;
- _DtCvUnit startX;
- _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
- _DtCvSegmentI *pSeg;
- _DtCvValue lstVisible = False;
- _DtCvValue found = False;
- _DtCvValue junk;
- _DtCvUnit endX;
- void *pChar;
- /*
- * get the line index
- */
- line = canvas->trav_lst[indx].idx;
- /*
- * get some information from the line
- */
- pSeg = canvas->txt_lst[line].seg_ptr;
- count = canvas->txt_lst[line].length;
- startChar = canvas->txt_lst[line].byte_index;
- startX = canvas->txt_lst[line].text_x;
- *ret_y = canvas->txt_lst[line].baseline - canvas->txt_lst[line].ascent;
- *ret_height = canvas->txt_lst[line].ascent + canvas->txt_lst[line].descent;
- while (count > 0 && !found && pSeg != NULL)
- {
- if (startX < canvas->txt_lst[line].text_x)
- startX = canvas->txt_lst[line].text_x;
- /*
- * adjust the starting position by the link space
- */
- junk = _DtCvIsSegVisibleLink(pSeg);
- lstVisible = _DtCvModifyXpos (canvas->link_info, pSeg, junk,
- lstVisible, lnkIndx, &startX);
- /*
- * adjust the starting position by the traversal space
- */
- junk = _DtCvIsSegALink(pSeg);
- (void) _DtCvModifyXpos (canvas->traversal_info, pSeg, junk,
- ((_DtCvValue) True), lnkIndx, &startX);
- lnkIndx = pSeg->link_idx;
- /*
- * skip no-op
- */
- if (_DtCvIsSegNoop(pSeg))
- len = 0;
-
- /*
- * check region
- */
- else if (_DtCvIsSegRegion(pSeg))
- {
- len = 1;
- endX = startX + _DtCvWidthOfRegionSeg(pSeg);
- }
- else
- {
- /*
- * initialize the pointer to the string
- */
- pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
- _DtCvIsSegWideChar(pSeg), startChar);
-
- /*
- * get the length of the current string.
- * If it is longer than the line count indicates,
- * it must be wrapped to the next line. We are
- * only interested in in the part of the line
- * that is on the line selected.
- */
- len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(pSeg));
- if (len > count)
- len = count;
-
- /*
- * calculate the ending pixel postion for
- * this string segment.
- */
- endX = startX + _DtCvGetStringWidth(canvas,pSeg,pChar,len);
- }
- /*
- * test to see if the selected segment was this segment.
- */
- if (pSeg == canvas->trav_lst[indx].seg_ptr)
- {
- found = True;
- *ret_x = startX;
- *ret_width = endX - startX;
- }
- else
- {
- /*
- * go to the next segment.
- */
- pSeg = pSeg->next_disp;
- /*
- * adjust for the new begining.
- */
- startX = endX;
- count = count - len;
- startChar = 0;
- }
- }
- return found;
- }
- /******************************************************************************
- * Function: CheckId
- *
- * Check to see if the id matches the target id.
- * If so, set the 'found id' flag and indicate its y coordinate.
- *****************************************************************************/
- static void
- CheckId(
- LayoutInfo *layout,
- char *id)
- {
- if (layout->target_id != NULL && NULL != id &&
- _DtCvStrCaseCmpLatin1(id, layout->target_id) == 0)
- {
- layout->id_Ypos = layout->info.y_pos;
- layout->id_found = True;
- }
- }
- /******************************************************************************
- * Function: CheckSetLineStart
- *
- * Check to see if the line information is at the beginning.
- * If so, set the pointers to the current segment and offset.
- *****************************************************************************/
- static void
- CheckSetLineStart(
- LayoutInfo *layout,
- _DtCvSegmentI *cur_seg)
- {
- if (layout->info.line_bytes == 0)
- {
- layout->info.line_seg = cur_seg;
- layout->info.line_start = 0;
- }
- }
- /******************************************************************************
- * Function: CheckForPageBreak
- *
- * Check to see if there is a page break on this segment.
- * If so, remember its position.
- *****************************************************************************/
- static int
- CheckForPageBreak(
- _DtCanvasStruct *canvas,
- _DtCvSegmentI *cur_seg,
- _DtCvUnit position)
- {
- /*
- * does this segment cause a page break?
- */
- if (_DtCvIsSegPageBreak(cur_seg))
- {
- /*
- * check to see if there is room to save the page break.
- * if not, allocate more room.
- */
- if (canvas->brk_cnt >= canvas->brk_max)
- {
- canvas->brk_max += GROW_SIZE;
- if (NULL != canvas->pg_breaks)
- canvas->pg_breaks = (_DtCvUnit *) realloc (
- (void *) canvas->pg_breaks,
- (sizeof(_DtCvUnit) * canvas->brk_max));
- else
- canvas->pg_breaks = (_DtCvUnit *) malloc (
- (sizeof(_DtCvUnit) * canvas->brk_max));
- }
- /*
- * failed to allocate memory, abort.
- */
- if (NULL == canvas->pg_breaks)
- {
- canvas->brk_max = 0;
- canvas->brk_cnt = 0;
- return 1;
- }
- /*
- * save the y position of the page break for later.
- */
- canvas->pg_breaks[canvas->brk_cnt++] = position;
- }
- return 0;
- }
- /******************************************************************************
- * Function: SetBeginCounts
- *
- * Parameters:
- * canvas Specifies the canvas.
- * f_info Specifies the layout count info.
- *
- * Returns: Nothing
- *
- * Purpose: Initializes the layout count information for a container.
- *****************************************************************************/
- static void
- SetBeginCounts (
- _DtCanvasStruct *canvas,
- CntInfo *cnt_info)
- {
- /*
- * text counts
- */
- cnt_info->beg_txt = canvas->txt_cnt;
- cnt_info->end_txt = canvas->txt_cnt;
- /*
- * line counts
- */
- cnt_info->beg_ln = canvas->line_cnt;
- cnt_info->end_ln = canvas->line_cnt;
- /*
- * break counts
- */
- cnt_info->beg_brk = canvas->brk_cnt;
- cnt_info->end_brk = canvas->brk_cnt;
- }
- /******************************************************************************
- * Function: SetEndCounts
- *
- * Parameters:
- * canvas Specifies the canvas.
- * f_info Specifies the layout count info.
- *
- * Returns: Nothing
- *
- * Purpose: Sets the ending layout counts for a container.
- *****************************************************************************/
- static void
- SetEndCounts (
- _DtCanvasStruct *canvas,
- CntInfo *cnt_info,
- int end_ln)
- {
- /*
- * text counts
- */
- cnt_info->end_txt = canvas->txt_cnt;
- /*
- * line counts
- */
- cnt_info->end_ln = canvas->line_cnt;
- /*
- * break counts
- */
- cnt_info->end_brk = canvas->brk_cnt;
- /*
- * the number of lines for this container.
- * If negative, indicates the first line is for the
- * bottom of the container and goes the length.
- */
- cnt_info->my_lines = end_ln;
- }
- /******************************************************************************
- * Function: SkipToNumber
- *
- * Returns:
- *****************************************************************************/
- static void
- SkipToNumber (
- const char **string)
- {
- if (string != NULL)
- {
- const char *str = *string;
- while (*str == ' ' && *str != '\0')
- str++;
- *string = str;
- }
- }
- /******************************************************************************
- * Function: GetValueFromString
- *
- * Returns:
- *****************************************************************************/
- static int
- GetValueFromString (
- const char **string,
- int def_num)
- {
- int value = def_num;
- if (string != NULL && *string != NULL && **string != '\0')
- {
- const char *str = *string;
- if ('0' <= *str && *str <= '9')
- value = atoi(str);
- while ('0' <= *str && *str <= '9')
- str++;
- while (*str != ' ' && *str != '\0' && (*str < '0' || *str > '9'))
- str++;
- *string = str;
- }
- return value;
- }
- /******************************************************************************
- * Function: PushDataPoint
- *
- * Returns:
- *****************************************************************************/
- static void
- PushDataPoint (
- LayoutInfo *layout,
- DataPoint *data_pt)
- {
- data_pt->x_units = 0;
- data_pt->next_pt = layout->data_pts;
- layout->data_pts = data_pt;
- }
- /******************************************************************************
- * Function: InsertDataPoint
- *
- * Returns:
- *****************************************************************************/
- static void
- InsertDataPoint (
- LayoutInfo *layout,
- DataPoint *data_pt)
- {
- DataPoint *lastPt = NULL;
- DataPoint *nextPt = layout->data_pts;
- while (nextPt != NULL &&
- nextPt->y_pos != _CEFORMAT_ALL &&
- (data_pt->y_pos == _CEFORMAT_ALL || nextPt->y_pos < data_pt->y_pos))
- {
- lastPt = nextPt;
- nextPt = nextPt->next_pt;
- }
- data_pt->next_pt = nextPt;
- data_pt->x_units = 0;
- if (lastPt == NULL)
- layout->data_pts = data_pt;
- else
- lastPt->next_pt = data_pt;
- }
- /******************************************************************************
- * Function: RemoveDataPoint
- *
- * Returns:
- *****************************************************************************/
- static void
- RemoveDataPoint (
- LayoutInfo *layout,
- DataPoint *data_pt)
- {
- DataPoint *lastPt = NULL;
- DataPoint *curPt = layout->data_pts;
- while (curPt != NULL && curPt != data_pt)
- {
- lastPt = curPt;
- curPt = curPt->next_pt;
- }
- if (curPt != NULL)
- {
- data_pt->x_units = layout->info.cur_max_x - data_pt->left;
- if (lastPt == NULL)
- layout->data_pts = curPt->next_pt;
- else
- lastPt->next_pt = curPt->next_pt;
- }
- }
- /******************************************************************************
- * Function: GetCurrentDataPoint
- *
- * Returns:
- *****************************************************************************/
- static void
- GetCurrentDataPoint (
- LayoutInfo *layout,
- DataPoint *data_pt)
- {
- data_pt->left = 0;
- data_pt->right = 0;
- data_pt->y_pos = _CEFORMAT_ALL;
- if (layout->data_pts != NULL)
- *data_pt = *(layout->data_pts);
- }
- /******************************************************************************
- * Function: SetMargins
- *
- * Purpose: Sets the margins.
- *****************************************************************************/
- static void
- SetMargins (
- LayoutInfo *layout)
- {
- layout->lmargin = 0;
- layout->rmargin = 0;
- layout->info.format_y = _CEFORMAT_ALL;
- if (layout->data_pts != NULL)
- {
- /*
- * base
- */
- layout->lmargin = layout->data_pts->left;
- layout->rmargin = layout->data_pts->right;
- layout->info.format_y = layout->data_pts->y_pos;
- }
- layout->lmargin += layout->left;
- layout->rmargin += layout->right;
- }
- /******************************************************************************
- * Function: SetTextPosition
- *
- * Purpose: Sets the text beginning position to the left margin.
- * If 'first' is true, adds its value to the text beginning
- * position value.
- *****************************************************************************/
- static void
- SetTextPosition (
- LayoutInfo *layout,
- _DtCvValue first)
- {
- layout->info.text_x_pos = layout->lmargin;
- if (first == True)
- layout->info.text_x_pos += layout->first;
- }
- /******************************************************************************
- * Function: CheckFormat
- *
- * Purpose: Checks to see if the flowing txt boundaries have been exceeded.
- * If a boundary has been exceeded, then removes that boundary
- * information from the stack until it finds a valid boundary point.
- *
- * Calls SetMargins to set the correct margin
- * Calls SetTextPosition to set the text beginning position.
- *****************************************************************************/
- static void
- CheckFormat (
- LayoutInfo *layout,
- _DtCvValue first)
- {
- while (layout->data_pts != NULL &&
- layout->data_pts->y_pos != _CEFORMAT_ALL &&
- layout->data_pts->y_pos < layout->info.y_pos)
- RemoveDataPoint (layout, layout->data_pts);
- SetMargins(layout);
- SetTextPosition(layout, first);
- }
- /******************************************************************************
- * Function: SaveLine
- *
- * Initializes a line table element to the segment it should display.
- *****************************************************************************/
- static void
- SaveLine (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- int direction,
- _DtCvPointer data,
- _DtCvUnit line_width,
- _DtCvUnit x,
- _DtCvUnit y,
- _DtCvUnit length)
- {
- int i = canvas->line_cnt;
- _DtCvUnit x2 = x;
- _DtCvUnit y2 = y;
- if (i >= canvas->line_max)
- {
- canvas->line_max += GROW_SIZE;
- if (canvas->line_lst)
- canvas->line_lst = (_DtCvLineSeg *) realloc (
- (void *) canvas->line_lst,
- (sizeof(_DtCvLineSeg) * canvas->line_max));
- else
- canvas->line_lst = (_DtCvLineSeg *) malloc (
- (sizeof(_DtCvLineSeg) * canvas->line_max));
- /*
- * NOTE....should this routine return a value?
- * If (re)alloc error occurs, this simply ignores the problem.
- */
- if (canvas->line_lst == NULL)
- {
- canvas->line_max = 0;
- canvas->line_cnt = 0;
- return;
- }
- }
- /*
- * does this line exceed the current maximum?
- */
- if (_DtCvLINE_HORZ == direction)
- {
- x2 += length;
- y2 += line_width;
- }
- else
- {
- x2 += line_width;
- y2 += length;
- }
- if (layout->info.max_x_pos < x2)
- layout->info.max_x_pos = x2;
- if (layout->info.cur_max_x < x2)
- layout->info.cur_max_x = x2;
- /*
- * save the line information
- */
- canvas->line_lst[i].dir = direction;
- canvas->line_lst[i].pos_x = x;
- canvas->line_lst[i].max_x = x2;
- canvas->line_lst[i].pos_y = y;
- canvas->line_lst[i].max_y = y2;
- canvas->line_lst[i].width = line_width;
- canvas->line_lst[i].data = data;
- canvas->line_cnt++;
- }
- /******************************************************************************
- * Function: SaveInfo
- *
- * Purpose: Saves the current information into the txt line struct.
- * Checks to see if this line exceeds the flowing text
- * boundary and resets the internal global margins.
- *****************************************************************************/
- static void
- SaveInfo (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *new_seg,
- int start)
- {
- _DtCvSaveInfo (canvas, &(layout->info),
- layout->max_width, layout->rmargin, layout->txt_justify);
- while (layout->info.delayed_search_saves > 0) {
- _DtCvSetSearchEntryInfo(canvas, canvas->txt_cnt - 1);
- layout->info.delayed_search_saves--;
- }
- layout->super_end = 0;
- layout->sub_end = 0;
- layout->super_script = False;
- layout->sub_script = False;
- layout->info.line_seg = new_seg;
- layout->info.line_start = start;
- layout->info.cur_len = 0;
- CheckFormat(layout, FALSE);
- }
- /******************************************************************************
- * Function: CheckSaveInfo
- *
- * Purpose: Checks to see if there is any information to save and saves
- * it if there is any.
- *****************************************************************************/
- static void
- CheckSaveInfo (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *new_seg,
- int start)
- {
- if (layout->info.line_bytes)
- SaveInfo (canvas, layout, new_seg, start);
- }
- /******************************************************************************
- * Function: ProcessStringSegment
- *
- * chops a string segment up until its completely used.
- *
- *****************************************************************************/
- static void
- ProcessStringSegment(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *cur_seg)
- {
- layout->cur_start = 0;
- if (!(_DtCvIsSegSuperScript(cur_seg) || _DtCvIsSegSubScript(cur_seg))
- && (layout->super_script == True || layout->sub_script == True))
- {
- layout->super_end = 0;
- layout->sub_end = 0;
- layout->super_script = False;
- layout->sub_script = False;
- }
- while (_DtCvProcessStringSegment(canvas, &(layout->info),
- layout->max_width, layout->lmargin, layout->rmargin,
- cur_seg , &(layout->cur_start),
- layout->txt_justify, layout->stat_flag) == 1)
- CheckFormat(layout, False);
- } /* End ProcessStringSegment */
- /******************************************************************************
- * Function: _DtCvUnit ResolveHeight(
- *
- * Parameters:
- *
- * Purpose: Determines the height of a row that is spanned.
- *****************************************************************************/
- static _DtCvUnit
- ResolveHeight(
- RowSpec *row_info,
- CellInfo *cell_info,
- int max_cols,
- int row,
- int span)
- {
- int i;
- int col;
- int cell;
- int topRow;
- int topCell;
- int zeroed;
- int total;
- int rowHeight = 0;
- for (col = 0, cell = row * max_cols; col < max_cols; col++, cell++)
- {
- /*
- * if we have a row spanning cell in this column,
- * but it isn't from a previous column, try to fill out
- * the height using it.
- */
- if (cell_info[cell].row_spn == -1 && cell_info[cell].col_spn != -1)
- {
- /*
- * back up to the cell information containing the row
- * span value.
- */
- topRow = row;
- topCell = cell;
- do
- {
- topCell--;
- topRow--;
- } while (cell_info[topCell].row_spn == -1);
- /*
- * from here, start calculating the height of the row
- * spanning cell, and find out how big the row must
- * be to contain it.
- */
- i = cell_info[topCell].row_spn;
- zeroed = span + 1;
- total = 0;
- while (i > 0 && zeroed > 0)
- {
- total += row_info[topRow].height;
- if (row_info[topRow].height == 0)
- zeroed--;
- i--;
- topRow++;
- }
- /*
- * if zeroed is greater than zero, that means only the
- * allowd number of row heights were zeroed out (the ones
- * we are looking for).
- * go ahead and calculate a new height. Otherwise,
- * it may be tried later.
- */
- if (zeroed > 0)
- {
- /*
- * make sure we get a positive value out of
- * this for our height.
- */
- if (cell_info[topCell].info.height > total)
- {
- total = cell_info[topCell].info.height - total;
- total = total / span + (total % span ? 1 : 0);
- }
- /*
- * make sure we take the biggest value possible
- * for this row. If it needs to be smaller for
- * cells, we'll adjust the positioning within
- * the cell.
- */
- if (rowHeight < total)
- rowHeight = total;
- }
- }
- }
- row_info[row].height = rowHeight;
- return rowHeight;
- }
- /******************************************************************************
- * Function: void AdjustHeight(
- *
- * Parameters:
- *
- * Purpose: Determines the height of rows that are spanned but the
- * the spanner needs more room than the calculated row height
- * allow.
- *****************************************************************************/
- static void
- AdjustHeight(
- CellInfo *cell_info,
- RowSpec *row_specs,
- int max_cols,
- int row,
- int col)
- {
- int cell = row * max_cols + col;
- int i, j;
- _DtCvUnit total;
- _DtCvUnit adjustValue;
- _DtCvUnit value;
- if (cell_info[cell].col_spn == -1 || cell_info[cell].row_spn == -1)
- return;
- for (j = row, i = 0, total = 0; i < cell_info[cell].row_spn; i++, j++)
- total += row_specs[j].height;
- /*
- * adjust the row height to include all of the row spanning cell.
- */
- if (total < cell_info[cell].info.height)
- {
- _DtCvUnit totalUsed = 0;
- /*
- * first, try to grow the cells on a percentage basis.
- * This way, a small cell will grow the same amount relative
- * to the larger cells.
- */
- adjustValue = cell_info[cell].info.height - total;
- /*
- * now if total is zero, we'll get a divide by zero error.
- * So check for this and set total to the number of rows spanned.
- */
- if (0 == total)
- total = cell_info[cell].row_spn;
- for (i = 0; i < cell_info[cell].row_spn; i++)
- {
- value = (((row_specs[row + i].height * 100) / total) * adjustValue)
- / 100;
- row_specs[row + i].height += value;
- totalUsed += value;
- }
- /*
- * if didn't use all the size up - apply it evenly.
- */
- if (totalUsed < adjustValue)
- {
- adjustValue = adjustValue - totalUsed;
- for (i = 0, j = cell_info[cell].row_spn;
- adjustValue > 0 && i < cell_info[cell].row_spn; i++, j--)
- {
- value = adjustValue / j + (adjustValue % j ? 1 : 0);
- row_specs[row + i].height += value;
- adjustValue -= value;
- totalUsed += value;
- }
- }
- total = totalUsed;
- }
- }
- /******************************************************************************
- * Function: void ReFormatCell(
- *
- * Parameters:
- * canvas Specifies the specific information about the
- * rendering area.
- * layout Specifies the currently active information
- * affecting the layout of information.
- *
- * Purpose: Based on a height and width, relay out the information in a cell.
- *****************************************************************************/
- static void
- ReFormatCell(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- CellInfo *this_cell,
- ColumnSpec *col_specs,
- int col,
- _DtCvUnit new_height,
- _DtCvUnit new_y)
- {
- int i;
- int saveTxt = canvas->txt_cnt;
- int saveLn = canvas->line_cnt;
- _DtCvUnit saveYpos = layout->info.y_pos;
- _DtCvUnit saveMaxX = layout->info.cur_max_x;
- _DtCvUnit cellWidth = 0;
- _DtCvUnit junk;
- _DtCvValue junkValue;
- DataPoint basePt;
- /*
- * reset the y_pos to the correct placement.
- * reset the line counts to the original values.
- * since we aren't changing the width, the number
- * of lines used will not change.
- */
- layout->info.y_pos = new_y;
- canvas->txt_cnt = this_cell->info.cnt.beg_txt;
- canvas->line_cnt = this_cell->info.cnt.beg_ln;
- /*
- * determine the maximum width for the cell.
- */
- for (i = this_cell->col_spn; i > 0; i--)
- cellWidth += col_specs[col++].actual;
- /*
- * get the current left and right margins.
- */
- GetCurrentDataPoint(layout, &basePt);
- /*
- * re-format the cell
- */
- FormatCell(canvas, layout, this_cell->cell_seg, cellWidth,
- new_height,
- basePt, &i, &cellWidth, &junk, &junkValue);
- /*
- * calculate the new height.
- */
- this_cell->info.height = layout->info.y_pos - new_y;
- /*
- * if the new cell does not use the same number of lines as the
- * old formatting did, zero the length.
- */
- while (canvas->txt_cnt < this_cell->info.cnt.end_txt)
- canvas->txt_lst[canvas->txt_cnt++].length = 0;
- /*
- * restore the saved counters
- */
- canvas->txt_cnt = saveTxt;
- canvas->line_cnt = saveLn;
- layout->info.y_pos = saveYpos;
- layout->info.cur_max_x = saveMaxX;
- }
- /******************************************************************************
- * Function: void FormatCell(
- *
- * Parameters:
- * canvas Specifies the specific information about the
- * rendering area.
- * layout Specifies the currently active information
- * affecting the layout of information.
- * span_width Specifies the desired size constraining
- * the layout of information.
- * base_pt Specifies the base margins.
- * this_cell Specifies the cell structure to fill out.
- *
- * Purpose: Determines the width and height of the cell. Also the begin/end
- * counts on text, graphics and lines.
- *****************************************************************************/
- static void
- FormatCell(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *cell_seg,
- _DtCvUnit span_width,
- _DtCvUnit min_height,
- DataPoint base_pt,
- int *ret_ln,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_height,
- _DtCvValue *ret_tab_flag)
- {
- _DtCvStatus only1Col = True;
- _DtCvUnit maxX;
- _DtCvUnit minY = -1;
- _DtCvUnit saveYpos = layout->info.y_pos;
- _DtCvUnit saveRight = layout->right;
- _DtCvUnit saveMaxX = layout->info.cur_max_x;
- _DtCvSegmentI *nextSeg;
- /*
- * set the limits/margins
- * assume the left_margin has been set by a previous call.
- */
- layout->right = layout->max_width - base_pt.left - base_pt.right
- - layout->left - span_width;
- /*
- * set the minimum Y for the container.
- */
- if (0 < min_height)
- minY = saveYpos + min_height;
- /*
- * If a segment was specified for this cell, format it.
- */
- if (cell_seg != NULL && &BlankTableCell != cell_seg)
- {
- ProcessContainer(canvas, layout, cell_seg, minY,
- ret_width, &maxX, ret_ln);
- /*
- * check to see if the only thing in this container is a
- * table.
- */
- nextSeg = _DtCvContainerListOfSeg(cell_seg);
- *ret_tab_flag = True;
- while (True == *ret_tab_flag && NULL != nextSeg)
- {
- /*
- * check to see if there is any segments that aren't one
- * column tables.
- */
- if (_DtCvIsSegTable(nextSeg) &&
- 1 < _DtCvNumColsOfTableSeg(nextSeg))
- only1Col = False;
- else if (!(_DtCvIsSegTable(nextSeg) || _DtCvIsSegNoop(nextSeg)))
- *ret_tab_flag = False;
- nextSeg = _DtCvNextSeg(nextSeg);
- }
- if (True == *ret_tab_flag && True == only1Col)
- *ret_tab_flag = False;
- }
- /*
- * Calculate the height and return it.
- */
- *ret_height = layout->info.y_pos - saveYpos;
- /*
- * restore the right margin
- */
- layout->right = saveRight;
- if (layout->info.cur_max_x < saveMaxX)
- layout->info.cur_max_x = saveMaxX;
- }
- /******************************************************************************
- * Function: AdjustFrmtTxtOption
- *
- *****************************************************************************/
- static void
- AdjustFrmtTxtOption(
- _DtCvSegmentI *p_seg,
- _DtCvFrmtOption option)
- {
- if (p_seg != NULL && _DtCvIsSegContainer(p_seg))
- {
- TxtHorizJustify(p_seg) = option;
- p_seg = _DtCvContainerListOfSeg(p_seg);
- while (p_seg != NULL)
- {
- AdjustFrmtTxtOption(p_seg, option);
- p_seg = p_seg->next_seg;
- }
- }
- }
- /******************************************************************************
- * Function: ResolveCell
- *
- *****************************************************************************/
- static _DtCvValue
- ResolveCell(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *table,
- ColumnSpec *col_specs,
- RowSpec *row_specs,
- int col,
- int row,
- int max_cols,
- int max_rows,
- CellInfo *ret_info)
- {
- register int i;
- char *id;
- char *idRefs;
- char *ptr;
- char c;
- int count;
- int len;
- int done;
- int brdCnt;
- int myCol = col;
- int cell = row * max_cols + col;
- _DtCvUnit cellWidth;
- _DtCvUnit retWidth;
- _DtCvUnit retHeight;
- _DtCvUnit saveTop;
- CellInfo *thisCell = &ret_info[cell];
- DataPoint basePt;
- _DtCvValue reformat = False;
- _DtCvValue retTabFlag = False;
- _DtCvSegmentI **f_data = _DtCvCellsOfTableSeg(table);
- /*
- * if this column is spanned, skip
- */
- if (thisCell->col_spn == -1 || thisCell->row_spn == -1)
- return False;
- GetCurrentDataPoint(layout, &basePt);
- if (thisCell->cell_seg == NULL)
- {
- idRefs = row_specs[row].next_id;
- /*
- * find the end of the id
- */
- done = False;
- /*
- * set the starting info
- */
- thisCell->col_spn = 1;
- thisCell->pos_x = basePt.left + layout->left;
- while (!done && col < max_cols)
- {
- ptr = idRefs;
- id = idRefs;
- /*
- * move the ptr to the next id,
- * counting the characters in this id at the same time.
- */
- len = 0;
- while (NULL != ptr && *ptr != ' ' && *ptr != '\0')
- {
- ptr++;
- len++;
- }
- /*
- * set idRefs to the next id.
- */
- idRefs = ptr;
- while (NULL != idRefs && *idRefs == ' ')
- idRefs++;
- /*
- * Is this id and the next the same? If so,
- * it spans the columns
- */
- if (0 != len && _DtCvStrNCaseCmpLatin1(id, idRefs, len) == 0 &&
- (idRefs[len] == ' ' || idRefs[len] == '\0'))
- {
- col++;
- thisCell->col_spn++;
- ret_info[++cell].col_spn = -1;
- }
- else
- done = True;
- }
- row_specs[row].next_id = idRefs;
- /*
- * find the segment
- */
- if (NULL != id && '\0' != *id)
- {
- c = *ptr;
- *ptr = '\0';
- while (f_data != NULL && NULL != *f_data &&
- _DtCvStrCaseCmpLatin1(_DtCvContainerIdOfSeg(*f_data),id) != 0)
- f_data++;
- /*
- * make sure to break the link to the next segment.
- * Otherwise, the formatting routines will format too much
- * for the cell.
- */
- if (NULL != f_data && NULL != *f_data)
- {
- _DtCvNextSeg(*f_data) = NULL;
- /*
- * assign the data to this cell.
- */
- thisCell->cell_seg = *f_data;
- }
- else /* there is no id for this cell, use a blank container */
- thisCell->cell_seg = (struct _dtCvSegment*) &BlankTableCell;
- }
- else /* there is no id for this cell, use a blank container */
- thisCell->cell_seg = (struct _dtCvSegment*) &BlankTableCell;
- /*
- * how many rows does this cell span?
- */
- len = 0;
- if (NULL != id)
- len = strlen(id);
- for (done = False, count = 1, i = row + 1;
- 0 < len && i < max_rows && False == done; i++)
- {
- done = True;
- if (_DtCvStrNCaseCmpLatin1(id, row_specs[i].next_id, len) == 0 &&
- (row_specs[i].next_id[len] == ' ' ||
- row_specs[i].next_id[len] == '\0'))
- {
- int k;
- done = False;
- count++;
- /*
- * invalidate the columns spanned in this row
- */
- for (k = 0; k < thisCell->col_spn && k + myCol < max_cols; k++)
- {
- ret_info[i * max_cols + myCol + k].col_spn = -1;
- ret_info[i * max_cols + myCol + k].row_spn = -1;
- }
-
- idRefs = row_specs[i].next_id;
- do
- {
- /*
- * skip the current id.
- */
- while (*idRefs != ' ' && *idRefs != '\0')
- idRefs++;
- /*
- * skip the space to the next id.
- */
- while (*idRefs == ' ')
- idRefs++;
- /*
- * now test to see if this is a match
- * cycle if so. quit if the end of string
- * or not a match.
- */
- } while (*idRefs != '\0' &&
- _DtCvStrNCaseCmpLatin1(id, idRefs, len) == 0 &&
- (idRefs[len] == ' ' || idRefs[len] == '\0'));
- /*
- * the next non-spanned column in this row will use this id.
- */
- row_specs[i].next_id = idRefs;
- }
- }
- if (NULL != id && '\0' != *id)
- *ptr = c;
- thisCell->row_spn = count;
- }
- for (i = 0, cellWidth = 0; i < thisCell->col_spn; i++)
- cellWidth += col_specs[myCol + i].actual;
- /*
- * set the start line and text information
- */
- SetBeginCounts(canvas, &(thisCell->info.cnt));
- /*
- * check to see if this cell is overhung by a previous cell.
- * If so, zero the top margin. But remember and restore it
- * because resizing may eliminate the need for the overhang!
- */
- if (&BlankTableCell != thisCell->cell_seg)
- {
- saveTop = _DtCvContainerTMarginOfSeg(thisCell->cell_seg);
- if (_DtCvTRUE == col_specs[myCol].hanger
- && 0 != row_specs[row].y_adj && myCol > row_specs[row].column)
- _DtCvContainerTMarginOfSeg(thisCell->cell_seg) = 0;
- }
- /*
- * Format the cell
- */
- FormatCell(canvas, layout, thisCell->cell_seg, cellWidth,
- row_specs[row].height, basePt,
- &brdCnt, &retWidth, &retHeight, &retTabFlag);
- if (&BlankTableCell != thisCell->cell_seg)
- _DtCvContainerTMarginOfSeg(thisCell->cell_seg) = saveTop;
- /*
- * set some ending information
- */
- thisCell->info.height = retHeight;
- thisCell->info.width = retWidth;
- SetEndCounts(canvas, &(thisCell->info.cnt), brdCnt);
- /*
- * check the height against previous heights
- */
- if (row_specs[row].height < retHeight && thisCell->row_spn == 1)
- row_specs[row].height = retHeight;
- /*
- * check for run over of the desired widths
- */
- if (retWidth > cellWidth)
- {
- register int j;
- _DtCvUnit cellMax;
- _DtCvUnit maxSlop;
- _DtCvUnit value;
- _DtCvUnit percent;
- _DtCvUnit slopUsed = 0;
- _DtCvUnit slop = retWidth - cellWidth; /* the amount of room
- required of the neighbors */
- /*
- * set the reformat flag
- */
- if (False == retTabFlag)
- reformat = True;
- /*
- * determine the maximum size the column can occupy
- */
- for (j = 0, cellMax = 0;
- j < thisCell->col_spn && j + myCol < max_cols; j++)
- cellMax += col_specs[myCol+j].max;
-
- /*
- * determine the maximum available space from the neighbors.
- */
- for (j = myCol + thisCell->col_spn, maxSlop = 0; j < max_cols; j++)
- maxSlop = maxSlop + col_specs[j].actual - col_specs[j].min;
- /*
- * If the slop demanded is larger than available,
- * simply reduced the other column specifications to their smallest
- * values.
- */
- if (slop >= maxSlop)
- {
- for (j = myCol + thisCell->col_spn; j < max_cols; j++)
- col_specs[j].actual = col_specs[j].min;
- /*
- * Is it allowed for this column to 'hang over' the others?
- *
- * And is it the first one? I.e. don't allow more than one
- * cell per row to overhang it's neighbors.
- *
- * And only allow it if the vertical text justification places
- * the text at the top of the cell.
- */
- if (_DtCvTRUE == col_specs[myCol].hanger
- && 0 == row_specs[row].y_adj
- && _DtCvJUSTIFY_TOP == TxtVertJustify(thisCell->cell_seg))
- {
- /*
- * now set the other columns to start a little lower
- * in their objects. Remove the bottom margin from the
- * adjustment. One would hope that each of the containers
- * for the columns in the row have the same bottom margin
- * so that the overhung cell will push the next row down
- * by the appropriate amount.
- */
- row_specs[row].y_adj = retHeight -
- _DtCvContainerBMarginOfSeg(thisCell->cell_seg);
- row_specs[row].column = myCol;
- retWidth = cellMax;
- /*
- * clear the reformat flag
- */
- reformat = False;
- }
- }
- else if (slop > 0)
- {
- /*
- * the maximum slop available from the neighbors is
- * enough. Now take space from my neighbors based
- * on their orginal size. I.e. the larger they
- * are, the more I take from them.
- */
- for (j = myCol + thisCell->col_spn; j < max_cols; j++)
- {
- percent = col_specs[j].actual - col_specs[j].min;
- value = slop * percent / maxSlop;
- slopUsed += value;
- col_specs[j].actual -= value;
- }
- /*
- * if any more slop is needed, grab it on a strictly
- * straight basis.
- */
- do {
- slop -= slopUsed;
- for (j = myCol + thisCell->col_spn, slopUsed = 0;
- slop > slopUsed && j < max_cols; j++)
- {
- if (col_specs[j].actual > col_specs[j].min)
- {
- col_specs[j].actual--;
- slopUsed++;
- }
- }
- } while (slopUsed > 0 && slop > slopUsed);
- }
- /*
- * set the column width in the controlling column struct.
- */
- if (thisCell->col_spn == 1)
- {
- col_specs[myCol].actual = retWidth;
- }
- else
- {
- /*
- * how much to spread among the columns?
- */
- slop = cellMax - retWidth;
- /*
- * if the aggragate max width is smaller than required,
- * allocate the excess among the columns.
- */
- if (slop < 0)
- {
- /*
- * set the desired to the max and calculate the leftover
- * slop and the maximum desired size.
- */
- for (j = 0, slop = retWidth, maxSlop = 0;
- myCol + j < max_cols && j < thisCell->col_spn; j++)
- {
- col_specs[j].actual = col_specs[myCol + j].max;
- slop -= col_specs[myCol + j].max;
- maxSlop += col_specs[myCol + j].max;
- }
- /*
- * now allocate the leftover slop to each colum
- * based on the maximum desired size.
- */
- for (j = 0, slopUsed = 0;
- slop > slopUsed && myCol + j < max_cols
- && j < thisCell->col_spn; j++)
- {
- value = slop * col_specs[myCol + j].max / maxSlop;
- if (((slop*col_specs[myCol+j].max) % maxSlop) >= (maxSlop/2))
- value++;
- col_specs[myCol + j].actual += value;
- slopUsed += value;
- }
- }
- else if (slop > 0)
- {
- slopUsed = 0;
- for (j = myCol;
- j < max_cols && j < myCol + thisCell->col_spn; j++)
- {
- percent = col_specs[j].max - col_specs[j].actual;
- value = slop * percent / maxSlop;
- slopUsed += value;
- col_specs[j].actual += value;
- }
- do {
- slop -= slopUsed;
- for (j = myCol, slopUsed = 0; slop > slopUsed &&
- j < max_cols && j < myCol + thisCell->col_spn; j++)
- {
- if (col_specs[j].actual < col_specs[j].max)
- {
- col_specs[j].actual++;
- slopUsed++;
- }
- }
- } while (slopUsed > 0 && slop > slopUsed);
- }
- else /* if (slop == 0) */
- {
- for (j = 0; myCol + j < max_cols && j < thisCell->col_spn; j++)
- col_specs[j].actual = col_specs[myCol + j].max;
- }
- }
- }
- return reformat;
- }
- /******************************************************************************
- * Function: ProcessTable
- *
- *****************************************************************************/
- static void
- ProcessTable(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *table,
- _DtCvUnit min_y)
- {
- int a;
- int b;
- int c;
- int col;
- int row;
- int cell;
- int divisor;
- int maxCols;
- int maxRows;
- int maxRowSpn;
- int saveLnStart = canvas->line_cnt;
- int saveTxtStart = canvas->txt_cnt;
- int saveTravCnt = canvas->trav_cnt;
- _DtCvUnit workWidth;
- _DtCvUnit newLeft;
- _DtCvUnit saveLeft = layout->left;
- _DtCvUnit saveYpos = layout->info.y_pos;
- _DtCvUnit tableYpos;
- _DtCvUnit newHeight;
- _DtCvUnit newWidth;
- _DtCvUnit oldAlignPos;
- short anchorRow = -1;
- const char **widthStr;
- const char *saveAlignChar = layout->info.align_char;
- char **rowIds;
- char *alignCharacters = NULL;
- char alignBuf[16];
- _DtCvFrmtOption saveTxtJustify = layout->txt_justify;
- _DtCvFrmtOption colJustify = _DtCvJUSTIFY_LEFT;
- _DtCvFrmtOption *colJustSpec;
- _DtCvValue oldFound = layout->id_found;
- _DtCvValue haveBrds = False;
- _DtCvValue saveState = layout->table_flag;
- _DtCvValue saveAlignFlag = layout->info.align_flag;
- _DtCvValue saveAlignPos = layout->info.align_pos;
- _DtCvValue redo;
- CellInfo defCell;
- CellInfo *cellInfo = &defCell;
- ColumnSpec defColumn;
- ColumnSpec *colSpecs = &defColumn;
- RowSpec defRow;
- RowSpec *rowSpecs = &defRow;
- DataPoint basePt;
- GrpInfo grpInfo = DefGrpInfo;
- /*
- * get the base margins that the table will be working in.
- */
- GetCurrentDataPoint(layout, &basePt);
- /*
- * find out how many rows there are.
- */
- for (rowIds = _DtCvCellIdsOfTableSeg(table), maxRows = 0;
- rowIds != NULL && rowIds[maxRows] != NULL; maxRows++);
- if (maxRows == 0)
- return;
- /*
- * get the number of columns and the column widths
- */
- maxCols = _DtCvNumColsOfTableSeg(table);
- widthStr = (const char **)_DtCvColWOfTableSeg(table);
- colJustSpec = _DtCvColJustifyOfTableSeg(table);
- if (maxCols < 1)
- maxCols = 1;
- if (widthStr == NULL)
- widthStr = DefWidth;
- /*
- * determine the width the table has to work with.
- */
- workWidth = layout->max_width - basePt.left - basePt.right -
- layout->left - layout->right;
- if (workWidth < 0)
- workWidth = 0;
- /*
- * turn the string specifying column widths into units.
- */
- if (maxCols != 1)
- {
- colSpecs = (ColumnSpec *) malloc (sizeof(ColumnSpec) * maxCols);
- if (colSpecs == NULL)
- return;
- }
- if (maxRows != 1)
- {
- rowSpecs = (RowSpec *) malloc (sizeof(RowSpec) * maxRows);
- if (rowSpecs == NULL)
- {
- if (maxCols > 1)
- free(colSpecs);
- return;
- }
- }
- if (maxRows != 1 || maxCols != 1)
- {
- cellInfo = (CellInfo *) malloc (sizeof(CellInfo) * maxCols * maxRows);
- if (cellInfo == NULL)
- {
- if (maxCols > 1)
- free(colSpecs);
- if (maxRows > 1)
- free(rowSpecs);
- return;
- }
- }
- /*
- * for each column, process the width specification.
- * '+Optimal,Take,Give'
- *
- * + - means the cell can 'hang over' its neighbors.
- * It will take everything it can get and then
- * push the other below it. (Labeled lists).
- * Optimal - The desired percentage of the available space to
- * use for the column.
- * Take - The percentage amount the column will take from
- * other columns to make itself 'fit'.
- * Give - The percentage amount the column is willing to give up
- * to other columns for them to 'fit'.
- */
- for (col = 0, divisor = 0; col < maxCols; col++)
- {
- const char *nxtWidth = *widthStr;
- /*
- * move to the meat of the width specification string.
- */
- SkipToNumber(&nxtWidth);
- /*
- * set the correct 'allow hangers' flag.
- */
- colSpecs[col].hanger = _DtCvFALSE;
- if ('+' == *nxtWidth)
- {
- colSpecs[col].hanger = _DtCvTRUE;
- nxtWidth++;
- }
- /*
- * now process the O,G,T specification.
- */
- a = GetValueFromString(&nxtWidth, 1); if (a < 1) a = 1;
- b = GetValueFromString(&nxtWidth, 0); if (b < 0) b = 0;
- c = GetValueFromString(&nxtWidth, b); if (c > a) c = a;
- /*
- * for now just get the base percentages.
- */
- colSpecs[col].min = a - c;
- colSpecs[col].actual = a;
- colSpecs[col].max = a + b;
- /*
- * get the column justification.
- */
- if (NULL != colJustSpec)
- {
- colJustify = *colJustSpec;
- colJustSpec++;
- }
- colSpecs[col].justify = colJustify;
- if (_DtCvINHERIT == colJustify)
- colSpecs[col].justify = saveTxtJustify;
- /*
- * up the divisor value.
- */
- divisor += colSpecs[col].actual;
- /*
- * skip to the next set of width specifications
- */
- if (col + 1 < maxCols && NULL != widthStr[1])
- widthStr++;
- /*
- * initialize the cell information for the rows in this column
- */
- for (row = 0; row < maxRows; row++)
- {
- cellInfo[row * maxCols + col].cell_seg = NULL;
- cellInfo[row * maxCols + col].col_spn = 0;
- cellInfo[row * maxCols + col].row_spn = 0;
- cellInfo[row * maxCols + col].info = DefLayFrmtInfo;
- }
- }
- /*
- * initialize the row specs
- */
- newHeight = 0;
- if (-1 != min_y && 1 == maxRows)
- newHeight = min_y - saveYpos;
- for (row = 0; row < maxRows; row++)
- {
- rowSpecs[row].column = -1;
- rowSpecs[row].y_adj = 0;
- rowSpecs[row].height = newHeight;
- rowSpecs[row].height = newHeight;
- rowSpecs[row].next_id = rowIds[row];
- }
- /*
- * now figure the real values
- */
- if (divisor < 1)
- divisor = 1;
- for (col = 0; col < maxCols; col++)
- {
- colSpecs[col].min = workWidth * colSpecs[col].min / divisor;
- colSpecs[col].actual = workWidth * colSpecs[col].actual / divisor;
- colSpecs[col].max = workWidth * colSpecs[col].max / divisor;
- if (colSpecs[col].min < 1)
- colSpecs[col].min = 1;
- if (colSpecs[col].actual < 1)
- colSpecs[col].actual = 1;
- if (colSpecs[col].max < 1)
- colSpecs[col].max = 1;
- }
- /*
- * now process the table.
- */
- tableYpos = layout->info.y_pos;
- maxRowSpn = 1;
- alignCharacters = _DtCvJustifyCharsOfTableSeg(table);
- /*
- * set up the state of table processing and
- * the beginning line/text counts.
- */
- layout->table_flag = True;
- SetBeginCounts(canvas, &(grpInfo.cnt));
- /*
- * now process each column, row by row.
- * Doing it row by row allows the columns to shake out their
- * sizing with less reformatting.
- */
- for (col = 0; col < maxCols; col++)
- {
- /*
- * remember where this column starts.
- */
- saveTravCnt = canvas->trav_cnt;
- saveLnStart = canvas->line_cnt;
- saveTxtStart = canvas->txt_cnt;
- newLeft = layout->left;
- colJustify = layout->txt_justify;
- layout->txt_justify = colSpecs[col].justify;
- /*
- * initialize the JUSTIFY_NUM or JUSTIFY_CHAR information
- */
- layout->info.align_pos = 0;
- layout->info.align_char = PeriodStr;
- if (_DtCvJUSTIFY_CHAR == layout->txt_justify)
- {
- /*
- * are any alignment characters specified?
- */
- if (NULL != alignCharacters && '\0' != alignCharacters)
- {
- int len = mblen(alignCharacters, MB_CUR_MAX);
- /*
- * copy the character into a buffer
- */
- strncpy(alignBuf, alignCharacters, len);
- alignBuf[len] = '\0';
- layout->info.align_char = alignBuf;
- /*
- * are there more characters? If so increment for the
- * next column that may have JUSTIFY_CHAR. Otherwise,
- * leave alone and re-use for other columns.
- */
- if ('\0' != alignCharacters[len])
- alignCharacters += len;
- }
- /* no...then default */
- else
- layout->txt_justify = _DtCvJUSTIFY_LEFT;
- }
- do {
- /*
- * reset the counts to the start
- */
- canvas->trav_cnt = saveTravCnt;
- canvas->line_cnt = saveLnStart;
- canvas->txt_cnt = saveTxtStart;
- layout->left = newLeft;
- /*
- * for each row, format the cell in this columns
- */
- for (row = 0, redo = False, cell = col;
- row < maxRows && redo == False;
- row++, cell += maxCols)
- {
- /*
- * remember the old height
- */
- rowSpecs[row].lst_height = rowSpecs[row].height;
- /*
- * set the alignment flag for each column in the row.
- */
- layout->info.align_flag = False;
- if (_DtCvJUSTIFY_CHAR == layout->txt_justify ||
- _DtCvJUSTIFY_NUM == layout->txt_justify)
- layout->info.align_flag = True;
- /*
- * remember the alignment position
- */
- oldAlignPos = layout->info.align_pos;
- /*
- * layout all the cells jammed to the top of the table.
- * later, they get moved down to their position.
- */
- layout->info.y_pos = tableYpos;
- redo = ResolveCell(canvas, layout, table,
- colSpecs, rowSpecs, col, row,
- maxCols, maxRows, cellInfo);
- /*
- * check for maximum row span
- */
- if (maxRowSpn < cellInfo[cell].row_spn)
- maxRowSpn = cellInfo[cell].row_spn;
- /*
- * did the cell have borders?
- */
- if (0 != cellInfo[cell].info.cnt.my_lines)
- haveBrds = True;
- /*
- * check to see if the specified anchor has been found in
- * this row. If so, save some information for later use.
- */
- if (anchorRow == -1 && oldFound != layout->id_found)
- anchorRow = row;
- /*
- * check to see if the alignment position has changed.
- * for all but the first row!
- */
- if (0 != row && oldAlignPos != layout->info.align_pos)
- redo = True;
- }
- if (True == redo)
- {
- for (a = 0; a < row; a++)
- {
- /*
- * restore the old row heights for this column
- */
- rowSpecs[a].height = rowSpecs[a].lst_height;
- /*
- * reset the hanging cell information.
- */
- if (col == rowSpecs[a].column)
- {
- rowSpecs[a].column = -1;
- rowSpecs[a].y_adj = 0;
- }
- }
- }
- } while (redo == True);
-
- /*
- * push the next column to the right by size of this column
- */
- layout->left += colSpecs[col].actual;
- /*
- * restore the horizontal text justification
- */
- layout->txt_justify = colJustify;
- }
- /*
- * set the ending counts for the lines/text in the table.
- * and save the information as long as we are not a table
- * that is a descendant of some container with a border and
- * our cells include borders and we're going to have to honor
- * boundaries.
- */
- SetEndCounts(canvas, &(grpInfo.cnt), 0);
- if (_DtCvUSE_BOUNDARY_MOVE == canvas->constraint &&
- False == layout->brdr_flag && True == haveBrds)
- {
- GrpInfo *info = (GrpInfo *) malloc (sizeof(GrpInfo));
- /*
- * warning - nothing done if malloc error.
- */
- if (NULL != info)
- {
- /*
- * initialize to the line counts for the table
- */
- *info = grpInfo;
- /*
- * set the linked list information
- */
- info->next_info = layout->grp_lst;
- layout->grp_lst = info;
- }
- }
- /*
- * Now go back and search for zeroed row heights and fill them in
- * based on spanned rows. This can only happen if maxRowSpn is
- * greater than 1! Otherwise, a row height really did end up zero!
- */
- if (maxRowSpn > 1)
- {
- /*
- * try to resolve the zero height rows
- */
- for (a = 1, redo = True; redo && a < maxRowSpn; a++)
- {
- redo = False;
- for (row = 0; row < maxRows; row++)
- {
- if (rowSpecs[row].height == 0 &&
- ResolveHeight(rowSpecs, cellInfo, maxCols, row, a) == 0)
- redo = True;
- }
- }
-
- /*
- * if any of the rows comes up unresolved, force to an average
- * line height.
- *
- * But only do this if the first cell *does not* span all the rows
- * and columns.
- */
- if (redo &&
- cellInfo[0].row_spn != maxRows && cellInfo[0].col_spn != maxCols)
- {
- for (row = 0; row < maxRows; row++)
- {
- if (rowSpecs[row].height == 0)
- rowSpecs[row].height = canvas->metrics.line_height;
- }
- }
- /*
- * Now, double check that the row heights will accomodate
- * all the cells.
- */
- for (row = 0; row < maxRows; row++)
- for (col = 0; col < maxCols; col++)
- AdjustHeight(cellInfo, rowSpecs, maxCols, row, col);
- }
- /*
- * now check that the minimum heights used for the rows matches
- * or exceeds the minimum y position required.
- */
- if (-1 != min_y)
- {
- _DtCvUnit pad;
- for (newHeight = 0, row = 0; row < maxRows; row++)
- newHeight += rowSpecs[row].height;
- if (tableYpos + newHeight < min_y)
- {
- newHeight = tableYpos - min_y;
- for (row = 0; 0 < newHeight && row < maxRows; row++)
- {
- pad = (newHeight/(maxRows-row));
- rowSpecs[row].height += pad;
- newHeight -= pad;
- }
- }
- }
- /*
- * now reposition the cells based on the final row heights.
- */
- layout->info.y_pos = tableYpos;
- for (tableYpos = 0, cell = 0, row = 0; row < maxRows;
- tableYpos = tableYpos + rowSpecs[row].height + rowSpecs[row].y_adj,
- row++)
- {
- /*
- * check to see if the specified anchor has been found in this
- * row. If so, adjust the found position.
- */
- if (anchorRow == row)
- layout->id_Ypos += tableYpos;
- for (col = 0, layout->left = saveLeft; col < maxCols;
- layout->left += colSpecs[col++].actual, cell++)
- {
- if (cellInfo[cell].cell_seg != NULL)
- {
- /*
- * calculate the new height
- */
- for (newHeight = 0, a = 0; a < cellInfo[cell].row_spn; a++)
- {
- newHeight += rowSpecs[row + a].height;
- if (col != rowSpecs[row + a].column)
- newHeight += rowSpecs[row + a].y_adj;
- }
- /*
- * calculate the new width.
- */
- for (newWidth = 0, a = 0; a < cellInfo[cell].col_spn; a++)
- newWidth += colSpecs[col + a].actual;
- /*
- * now get the overhang space for this cell
- */
- workWidth = 0;
- if (col > rowSpecs[row].column)
- workWidth = rowSpecs[row].y_adj;
- /*
- * if the heights (and/or width for spanning columns)
- * are different, check to see if the
- * cell contains lines that may be affected by the
- * height adjustment.
- *
- * It is strongly assumed that if a table specifies that
- * a cell can hang over it's neighbors that it will *NOT*
- * have borders (whereby LinesMayChange is false) and
- * newWidth will not be greater than the cell's width.
- */
- if ((newHeight > cellInfo[cell].info.height &&
- True == LinesMayChange(canvas,
- cellInfo[cell].info.cnt.beg_ln,
- cellInfo[cell].info.cnt.end_ln,
- cellInfo[cell].info.cnt.my_lines))
- ||
- (1 < cellInfo[cell].col_spn &&
- newWidth > cellInfo[cell].info.width))
- ReFormatCell(canvas, layout, &cellInfo[cell], colSpecs,
- col, newHeight,
- layout->info.y_pos + tableYpos);
- else
- /* adjust the cell rather than reformatting */
- AdjustObjectPosition(canvas, layout,
- TxtVertJustify(cellInfo[cell].cell_seg),
- cellInfo[cell].info.cnt.beg_txt ,
- cellInfo[cell].info.cnt.beg_ln ,
- cellInfo[cell].info.cnt.beg_brk ,
- cellInfo[cell].info.cnt.end_txt ,
- cellInfo[cell].info.cnt.end_ln ,
- cellInfo[cell].info.cnt.end_brk ,
- cellInfo[cell].info.cnt.my_lines,
- newHeight - cellInfo[cell].info.height,
- 0,
- tableYpos, workWidth);
- }
- }
- }
- /*
- * increment the maximum y.
- */
- layout->info.y_pos += tableYpos;
- layout->left = saveLeft;
- if (maxCols > 1)
- free(colSpecs);
- if (maxRows > 1)
- free(rowSpecs);
- if (maxRows > 1 || maxCols > 1)
- free(cellInfo);
- layout->txt_justify = saveTxtJustify;
- layout->table_flag = saveState;
- /*
- * restore the alignment information
- */
- layout->info.align_flag = saveAlignFlag;
- layout->info.align_char = saveAlignChar;
- layout->info.align_pos = saveAlignPos;
- }
- /******************************************************************************
- * Function: UpdateDimensionArrays
- *
- * Purpose: Based on the object's orientation and justification,
- * update the correct dimension array(s).
- *
- *****************************************************************************/
- static void
- UpdateDimensionArrays(
- _DtCvSegmentI *p_seg,
- _DtCvUnit width,
- _DtCvUnit height,
- TopDims *top_bot,
- SideDims *side,
- CornerDims *corner,
- FlowDims *flow,
- _DtCvUnit *max_left,
- _DtCvUnit *max_right)
- {
- int i;
- int j;
- int *marginPtr;
- _DtCvFrmtOption orient = ObjHorizOrient(p_seg);
- _DtCvFrmtOption vOrient = ObjVertOrient(p_seg);
- /*
- * modify the width that headSize should be
- */
- j = DIMS_LM;
- i = DIMS_TOP;
- switch (orient)
- {
- case _DtCvJUSTIFY_RIGHT_MARGIN:
- j++;
- case _DtCvJUSTIFY_CENTER:
- j++;
- case _DtCvJUSTIFY_LEFT_MARGIN:
- if (vOrient == _DtCvJUSTIFY_BOTTOM)
- i = DIMS_BOTTOM;
- if ((*top_bot)[i][j][DIMS_WIDTH] < width)
- (*top_bot)[i][j][DIMS_WIDTH] = width;
- if (_DtCvWRAP_JOIN != _DtCvContainerFlowOfSeg(p_seg))
- (*top_bot)[i][j][DIMS_HEIGHT] += height;
- break;
- }
- /*
- * check left & right margins.
- */
- marginPtr = max_left;
- j = DIMS_LEFT;
- i = DIMS_TOP;
- switch(orient)
- {
- case _DtCvJUSTIFY_RIGHT_CORNER:
- case _DtCvJUSTIFY_RIGHT:
- j = DIMS_RIGHT;
- marginPtr = max_right;
- case _DtCvJUSTIFY_LEFT_CORNER:
- case _DtCvJUSTIFY_LEFT:
- if (vOrient != _DtCvJUSTIFY_TOP)
- i++;
- if (vOrient == _DtCvJUSTIFY_BOTTOM)
- i++;
- /*
- * push i to zero or 4
- */
- if (orient == _DtCvJUSTIFY_RIGHT_CORNER ||
- orient == _DtCvJUSTIFY_LEFT_CORNER)
- {
- if (i) i = DIMS_BC;
- (*corner)[i][j] += height;
- if (*marginPtr < width)
- *marginPtr = width;
- }
- else if (_DtCvContainerFlowOfSeg(p_seg) != _DtCvWRAP)
- {
- (*side)[i][j] += height;
- if (*marginPtr < width)
- *marginPtr = width;
- }
- else
- {
- (*flow)[j][DIMS_HEIGHT] += height;
- if ((*flow)[j][DIMS_WIDTH] < width)
- (*flow)[j][DIMS_WIDTH] = width;
- }
- break;
- }
- }
- /******************************************************************************
- * Function: DetermineMaxDims
- *
- *****************************************************************************/
- static void
- DetermineMaxDims(
- TopDims *top_bot,
- CornerDims *corner,
- _DtCvUnit left_margin,
- _DtCvUnit right_margin,
- _DtCvUnit *top_height,
- _DtCvUnit *bot_height,
- _DtCvUnit *max_width)
- {
- register int j;
- _DtCvUnit topWidth;
- _DtCvUnit botWidth;
- /*
- * now process all the information gathered about the (sub)headings
- * to determine the bounding box for the (head) txt. Start by figuring
- * out the maximums for the dimensions.
- *
- * figure the current top and bottom max widths.
- */
- topWidth = left_margin + right_margin;
- botWidth = left_margin + right_margin;
- *top_height = 0;
- *bot_height = 0;
- for (j = DIMS_LM; j <= DIMS_RM; j++)
- {
- topWidth = topWidth + (*top_bot)[DIMS_TOP] [j][DIMS_WIDTH];
- botWidth = botWidth + (*top_bot)[DIMS_BOTTOM][j][DIMS_WIDTH];
- if (*top_height < (*top_bot)[DIMS_TOP][j][DIMS_HEIGHT])
- *top_height = (*top_bot)[DIMS_TOP][j][DIMS_HEIGHT];
- if (*bot_height < (*top_bot)[DIMS_BOTTOM][j][DIMS_HEIGHT])
- *bot_height = (*top_bot)[DIMS_BOTTOM][j][DIMS_HEIGHT];
- }
- /*
- * for the maximum top and bottom heights, take into
- * consideration the corner values
- */
- if (*top_height < (*corner)[DIMS_TC][DIMS_LEFT])
- *top_height = (*corner)[DIMS_TC][DIMS_LEFT];
- if (*top_height < (*corner)[DIMS_TC][DIMS_RIGHT])
- *top_height = (*corner)[DIMS_TC][DIMS_RIGHT];
- if (*bot_height < (*corner)[DIMS_BC][DIMS_LEFT])
- *bot_height = (*corner)[DIMS_BC][DIMS_LEFT];
- if (*bot_height < (*corner)[DIMS_BC][DIMS_RIGHT])
- *bot_height = (*corner)[DIMS_BC][DIMS_RIGHT];
- *max_width = topWidth;
- if (*max_width < botWidth)
- *max_width = botWidth;
- }
- /******************************************************************************
- * Function: DetermineFlowConstraints
- *
- *****************************************************************************/
- static void
- DetermineFlowConstraints(
- LayoutInfo *layout,
- FlowDims flow_dims,
- _DtCvUnit left_margin,
- _DtCvUnit right_margin,
- _DtCvUnit start_y,
- DataPoint *left_pt,
- DataPoint *right_pt)
- {
- _DtCvUnit leftSide = flow_dims[DIMS_LEFT][DIMS_HEIGHT];
- _DtCvUnit rightSide = flow_dims[DIMS_RIGHT][DIMS_HEIGHT];
- /*
- * Now, if there is flowing text required, put points on the
- * stack to indicate them.
- */
- left_margin += flow_dims[DIMS_LEFT][DIMS_WIDTH];
- right_margin += flow_dims[DIMS_RIGHT][DIMS_WIDTH];
- GetCurrentDataPoint(layout, left_pt);
- GetCurrentDataPoint(layout, right_pt);
- left_pt->left += left_margin;
- left_pt->right += right_margin;
- left_pt->y_pos = _CEFORMAT_ALL;
- right_pt->left += left_margin;
- right_pt->right += right_margin;
- right_pt->y_pos = _CEFORMAT_ALL;
- while (leftSide > 0 || rightSide > 0)
- {
- if (leftSide > 0)
- {
- if (rightSide == 0 || leftSide <= rightSide)
- {
- left_pt->right = right_margin;
- left_pt->y_pos = start_y + leftSide;
- if (leftSide != rightSide)
- left_margin = 0;
- leftSide = 0;
- InsertDataPoint(layout, left_pt);
- }
- }
- if (rightSide > 0)
- {
- if (leftSide == 0 || leftSide > rightSide)
- {
- right_pt->left = left_margin;
- right_pt->y_pos = start_y + rightSide;
- if (leftSide != rightSide)
- right_margin = 0;
- rightSide = 0;
- InsertDataPoint(layout, right_pt);
- }
- }
- }
- }
- /******************************************************************************
- * Function: DetermineHeadPositioning
- *
- *****************************************************************************/
- static void
- DetermineHeadPositioning(
- TopDims *top_bot,
- SideDims *side,
- CornerDims *corner,
- FlowDims *flow,
- _DtCvUnit start_y,
- _DtCvUnit max_top,
- _DtCvUnit block_size,
- _DtCvUnit *ret_side_size)
- {
- int i;
- _DtCvUnit leftSideHeight = 0;
- _DtCvUnit rightSideHeight = 0;
- _DtCvUnit sideHeight = 0;
- /*
- * determine the maximum side heights
- */
- for (i = DIMS_TOP; i <= DIMS_BOTTOM; i++)
- {
- leftSideHeight += (*side)[i][DIMS_LEFT];
- rightSideHeight += (*side)[i][DIMS_RIGHT];
- }
- /*
- * determine the maximum side height
- */
- sideHeight = block_size;
- if (sideHeight < leftSideHeight)
- sideHeight = leftSideHeight;
- if (sideHeight < rightSideHeight)
- sideHeight = rightSideHeight;
- if (sideHeight < (*flow)[DIMS_LEFT][DIMS_HEIGHT])
- sideHeight = (*flow)[DIMS_LEFT][DIMS_HEIGHT];
- if (sideHeight < (*flow)[DIMS_RIGHT][DIMS_HEIGHT])
- sideHeight = (*flow)[DIMS_RIGHT][DIMS_HEIGHT];
- /*
- * calculate the starting Y position for each of the positions
- * reuse the arrays that were used to save the max dimension values.
- */
- for (i = DIMS_LM; i <= DIMS_RM; i++)
- {
- (*top_bot)[DIMS_TOP] [i][DIMS_YPOS] = start_y;
- (*top_bot)[DIMS_BOTTOM][i][DIMS_YPOS] = start_y + max_top + sideHeight;
- }
- (*corner)[DIMS_TC][DIMS_LEFT] = start_y;
- (*corner)[DIMS_TC][DIMS_RIGHT] = start_y;
- (*corner)[DIMS_BC][DIMS_LEFT] = start_y + max_top + sideHeight;
- (*corner)[DIMS_BC][DIMS_RIGHT] = start_y + max_top + sideHeight;
- (*side)[DIMS_TOP][DIMS_LEFT] = start_y + max_top;
- (*side)[DIMS_TOP][DIMS_RIGHT] = start_y + max_top;
- (*flow)[DIMS_LEFT ][DIMS_YPOS] = start_y + max_top;
- (*flow)[DIMS_RIGHT][DIMS_YPOS] = start_y + max_top;
- (*side)[DIMS_CENTER][DIMS_LEFT] = start_y + max_top +
- (sideHeight - (*side)[DIMS_CENTER][DIMS_LEFT]) / 2;
- (*side)[DIMS_CENTER][DIMS_RIGHT] = start_y + max_top +
- (sideHeight - (*side)[DIMS_CENTER][DIMS_RIGHT]) / 2;
- (*side)[DIMS_BOTTOM][DIMS_LEFT] = start_y + max_top +
- sideHeight - (*side)[DIMS_BOTTOM][DIMS_LEFT];
- (*side)[DIMS_BOTTOM][DIMS_RIGHT] = start_y + max_top +
- sideHeight - (*side)[DIMS_BOTTOM][DIMS_RIGHT];
- if (ret_side_size != NULL)
- *ret_side_size = sideHeight;
- }
- /******************************************************************************
- * Function: AdjustHead
- *
- * Parameters:
- * base_left Specifies the x position that the controller
- * occupying 'left_margin' space would start
- * at.
- * block_width Specifies the body's width for which to
- * center or align a controller with.
- * left_margin Specifies the space used by a controller
- * that is on the left side of the body.
- * right_margin Specifies the space used by a controller
- * on the right side of the body.
- *
- *****************************************************************************/
- static void
- AdjustHeadPosition(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *p_seg,
- TopDims *top_bot,
- SideDims *side,
- CornerDims *corner,
- FlowDims *flow,
- LayFrmtInfo *info,
- _DtCvUnit base_y,
- _DtCvUnit base_left,
- _DtCvUnit block_width,
- _DtCvUnit left_margin,
- _DtCvUnit right_margin)
- {
- int i = DIMS_TOP; /* also DIMS_TC */
- int j = DIMS_LEFT; /* also DIMS_LM */
- int divisor = 2;
- _DtCvUnit adjustX = 0;
- _DtCvUnit adjustY = 0;
- _DtCvUnit newY = 0;
- _DtCvUnit headWidth = info->width;
- _DtCvFrmtOption orient = ObjHorizOrient(p_seg);
- _DtCvFrmtOption vOrient = ObjVertOrient(p_seg);
- if (_DtCvContainerPercentOfSeg(p_seg) == 10000
- && orient == _DtCvJUSTIFY_CENTER
- && TxtHorizJustify(p_seg) == _DtCvJUSTIFY_LEFT)
- headWidth = block_width;
- switch (orient)
- {
- case _DtCvJUSTIFY_RIGHT_MARGIN:
- divisor = 1;
- j++;
- case _DtCvJUSTIFY_CENTER:
- adjustX = (block_width - headWidth) / divisor;
- j++;
- case _DtCvJUSTIFY_LEFT_MARGIN:
- adjustX += left_margin;
- if (vOrient == _DtCvJUSTIFY_BOTTOM)
- i = DIMS_BOTTOM;
- newY = (*top_bot)[i][j][DIMS_YPOS];
- (*top_bot)[i][j][DIMS_YPOS] += info->height;
- break;
- case _DtCvJUSTIFY_RIGHT_CORNER:
- adjustX = block_width + left_margin;
- j = DIMS_RIGHT;
- case _DtCvJUSTIFY_LEFT_CORNER:
- if (vOrient == _DtCvJUSTIFY_BOTTOM)
- i = DIMS_BC;
- newY = (*corner)[i][j];
- (*corner)[i][j] += info->height;
- break;
- case _DtCvJUSTIFY_RIGHT:
- adjustX = block_width + left_margin;
- j = DIMS_RIGHT;
- case _DtCvJUSTIFY_LEFT:
- if (vOrient != _DtCvJUSTIFY_TOP)
- i++;
- if (vOrient == _DtCvJUSTIFY_BOTTOM)
- i++;
- if (_DtCvContainerFlowOfSeg(p_seg) == _DtCvWRAP)
- {
- if (orient == _DtCvJUSTIFY_LEFT)
- adjustX += left_margin;
- else
- adjustX -= headWidth;
- newY = (*flow)[j][DIMS_YPOS];
- (*flow)[j][DIMS_YPOS] += info->height;
- }
- else
- {
- newY = (*side)[i][j];
- (*side)[i][j] += info->height;
- }
- break;
- }
- adjustY = newY - base_y;
- adjustX += base_left;
- /*
- * adjust the text positions
- */
- AdjustTextPositions(canvas, info->cnt.beg_txt, info->cnt.end_txt,
- adjustX, adjustY);
- /*
- * adjust the lines positions
- */
- AdjustLinePositions(canvas, info->cnt.beg_ln, info->cnt.end_ln,
- adjustX, adjustY);
- /*
- * adjust the page breaks, but only if necessary.
- */
- AdjustPgBrk(canvas, info->cnt.beg_brk, info->cnt.end_brk, adjustY);
- }
- /******************************************************************************
- * Function: InitDimArrays
- *
- *****************************************************************************/
- static void
- InitDimArrays(
- TopDims *top_bot,
- SideDims *side,
- CornerDims *corner,
- FlowDims *flow)
- {
- int i;
- int j;
- for (i = DIMS_TOP; i <= DIMS_BOTTOM; i++)
- {
- for (j = DIMS_LM; j <= DIMS_RM; j++)
- {
- (*top_bot)[i][j][DIMS_WIDTH] = 0;
- (*top_bot)[i][j][DIMS_HEIGHT] = 0;
- }
- for (j = DIMS_LEFT; j <= DIMS_RIGHT; j++)
- (*side)[i][j] = 0;
- }
- for (i = DIMS_LEFT; i <= DIMS_RIGHT; i++)
- {
- for (j = DIMS_WIDTH; j <= DIMS_HEIGHT; j++)
- {
- (*corner)[i][j] = 0;
- (*flow)[i][j] = 0;
- }
- }
- }
- /******************************************************************************
- * Function: ProcessController
- *****************************************************************************/
- static LayFrmtInfo *
- ProcessController(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *cur_seg)
- {
- int getLn;
- int saveTravCnt = canvas->trav_cnt;
- _DtCvUnit saveYPos = layout->info.y_pos;
- _DtCvUnit saveMaxWidth = layout->max_width;
- _DtCvUnit saveLeft = layout->left;
- _DtCvUnit saveRight = layout->right;
- _DtCvUnit maxWidth;
- _DtCvUnit maxXPos;
- _DtCvUnit myMaxWidth;
- LayFrmtInfo *frmtInfo;
- DataPoint basePt;
- DataPoint zeroPt;
- _DtCvValue redo;
- /*
- * Controllers always break the formatting sequence.
- * So save any information in the buffer, reset the margins and
- * add the appropriate lines, and check for going over boundaries.
- */
- CheckSaveInfo(canvas, layout, cur_seg, 0);
- CheckFormat(layout, True);
- /*
- * Get the controller specific information.
- * disallow some of the orientation & vOrient combinations
- */
- if ((ObjHorizOrient(cur_seg) == _DtCvJUSTIFY_CENTER
- && ObjVertOrient(cur_seg) != _DtCvJUSTIFY_BOTTOM)
- ||
- (ObjVertOrient(cur_seg) == _DtCvJUSTIFY_CENTER
- && ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_LEFT
- && ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_RIGHT))
- ObjVertOrient(cur_seg) = _DtCvJUSTIFY_TOP;
- if (_DtCvContainerFlowOfSeg(cur_seg) == _DtCvWRAP
- &&
- (ObjVertOrient(cur_seg) != _DtCvJUSTIFY_TOP
- ||
- (ObjVertOrient(cur_seg) == _DtCvJUSTIFY_TOP
- && ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_LEFT
- && ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_RIGHT)))
- _DtCvContainerFlowOfSeg(cur_seg) = _DtCvWRAP_NONE;
- if (_DtCvContainerFlowOfSeg(cur_seg) == _DtCvWRAP_JOIN
- &&
- (ObjVertOrient(cur_seg) != _DtCvJUSTIFY_TOP
- || ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_LEFT_MARGIN))
- {
- ObjVertOrient(cur_seg) = _DtCvJUSTIFY_TOP;
- ObjHorizOrient(cur_seg) = _DtCvJUSTIFY_LEFT_MARGIN;
- }
-
- /*
- * malloc a formatting dimension structure and initialize it with
- * default values. This will be returned to the caller.
- */
- frmtInfo = (LayFrmtInfo *) malloc (sizeof(LayFrmtInfo));
- *frmtInfo = DefLayFrmtInfo;
- /*
- * the controller object begins here.
- */
- SetBeginCounts(canvas, &(frmtInfo->cnt));
- /*
- * set the parent's data point in the stack
- */
- GetCurrentDataPoint(layout, &basePt);
- /*
- * calculate the amount of space the controller can occupy.
- * first calculate the amount of space to work with.
- * then truncate to zero if necessary.
- * then use the percentage of that remaining area as the space
- * the controller's segments can occupy.
- */
- myMaxWidth = layout->max_width - basePt.left - basePt.right
- - saveLeft - saveRight;
- if (myMaxWidth < 0)
- myMaxWidth = 0;
- myMaxWidth = (_DtCvUnit) (((double) myMaxWidth)
- * ((double) _DtCvContainerPercentOfSeg(cur_seg))
- / HeadDivisor);
- /*
- * Format the controller at a 'zero'ed point.
- * The lines it generates will be moved later to their correct position.
- */
- layout->left = 0;
- layout->right = 0;
- zeroPt = DefDataPt;
- PushDataPoint(layout, &zeroPt);
- /*
- * now process as a regular container
- */
- do {
- /*
- * set some counts and flags (necessary for a redo).
- */
- redo = False;
- canvas->trav_cnt = saveTravCnt;
- canvas->line_cnt = frmtInfo->cnt.beg_ln;
- canvas->txt_cnt = frmtInfo->cnt.beg_txt;
- layout->max_width = myMaxWidth;
- layout->info.y_pos = 0;
- /*
- * process the container
- */
- ProcessContainer(canvas,layout,cur_seg,-1,&maxWidth,&maxXPos,&getLn);
- /*
- * check to see if we need to reformat because the minimum size
- * is larger than we asked for.
- */
- if (maxXPos + _DtCvContainerRMarginOfSeg(cur_seg) > myMaxWidth)
- {
- redo = True;
- myMaxWidth = maxXPos + _DtCvContainerRMarginOfSeg(cur_seg);
- }
- } while (True == redo);
-
- /*
- * remove this element's data points from the stack.
- */
- RemoveDataPoint(layout, &zeroPt);
- /*
- * set the ending counts for the items in this container.
- */
- SetEndCounts(canvas, &(frmtInfo->cnt), getLn);
- frmtInfo->width = myMaxWidth;
- frmtInfo->height = layout->info.y_pos;
- /*
- * does this controller want to join with the lines in a non-controller?
- */
- if (_DtCvWRAP_JOIN == _DtCvContainerFlowOfSeg(cur_seg)
- && frmtInfo->cnt.beg_txt != canvas->txt_cnt)
- _DtCvSetJoinInfo(&(layout->info), True, canvas->txt_cnt - 1);
- /*
- * Restore the previous information
- */
- if (NULL != layout->lst_rendered)
- layout->lst_rendered->next_disp = NULL;
- layout->left = saveLeft;
- layout->right = saveRight;
- layout->max_width = saveMaxWidth;
- layout->lst_rendered = NULL;
- layout->info.y_pos = saveYPos;
- return frmtInfo;
- }
- /******************************************************************************
- * Function: AdjustForBorders
- *
- * Initializes the display line and graphic tables.
- *****************************************************************************/
- static void
- AdjustForBorders(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvFrmtOption brdr,
- _DtCvUnit line_width,
- _DtCvUnit *ret_bot,
- _DtCvUnit *ret_right)
- {
- /*
- * if the line_width is zero, make it 1 so that is really takes
- * up some space.
- */
- if (0 == line_width)
- line_width = 1;
- /*
- * set the flag for processing a border
- */
- if (_DtCvBORDER_NONE != brdr)
- layout->brdr_flag = True;
- /*
- * check to see if this element has a border. If so, adjust the
- * boundaries.
- */
- if (brdr == _DtCvBORDER_FULL || brdr == _DtCvBORDER_HORZ
- || brdr == _DtCvBORDER_TOP
- || brdr == _DtCvBORDER_TOP_LEFT
- || brdr == _DtCvBORDER_TOP_RIGHT)
- layout->info.y_pos += line_width;
- *ret_bot = 0;
- if (brdr == _DtCvBORDER_FULL || brdr == _DtCvBORDER_HORZ
- || brdr == _DtCvBORDER_BOTTOM
- || brdr == _DtCvBORDER_BOTTOM_LEFT
- || brdr == _DtCvBORDER_BOTTOM_RIGHT)
- *ret_bot = line_width;
- if (brdr == _DtCvBORDER_FULL || brdr == _DtCvBORDER_VERT
- || brdr == _DtCvBORDER_LEFT
- || brdr == _DtCvBORDER_TOP_LEFT
- || brdr == _DtCvBORDER_BOTTOM_LEFT)
- layout->left += line_width;
- *ret_right = 0;
- if (brdr == _DtCvBORDER_FULL || brdr == _DtCvBORDER_VERT
- || brdr == _DtCvBORDER_RIGHT
- || brdr == _DtCvBORDER_TOP_RIGHT
- || brdr == _DtCvBORDER_BOTTOM_RIGHT)
- {
- layout->right += line_width;
- *ret_right = line_width;
- }
- }
- /******************************************************************************
- * Function: DrawBorders
- *
- * Parameters:
- * canvas Specifies the virtual canvas on which
- * lines are drawn.
- * layout Specifies the current layout information.
- * brdr Specifies the type of border.
- * top_y Specifes the top y of the bounding box for
- * the object. Any border drawn should be
- * completely below this y.
- * bot_y Specifes the bottom y of the bounding box
- * for the object. Any border drawn should be
- * completely below this y.
- * left_x Specifies the left x of the bounding box
- * for the object. Any border drawn should be
- * completely to the right of this x.
- * right_x Specifies the right x of the bounding box
- * for the object. Any border drawn should be
- * completely to the left of this x.
- *
- * left_x right_x
- * | |
- * v v
- * top_y ---> xxxxxxxxxxxxxxxxxxxxxx
- * xxxxxxxxxxxxxxxxxxxxxx
- * xx------------------xx
- * xx| |xx (xx represents the line.)
- * xx| |xx
- * xx| |xx
- * xx| |xx
- * xx------------------xx
- * bot_y ---> xxxxxxxxxxxxxxxxxxxxxx
- * xxxxxxxxxxxxxxxxxxxxxx
- *
- *****************************************************************************/
- static int
- DrawBorders(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvFrmtOption brdr,
- _DtCvPointer data,
- _DtCvUnit line_width,
- _DtCvUnit top_y,
- _DtCvUnit bot_y,
- _DtCvUnit left_x,
- _DtCvUnit right_x)
- {
- int mod = 1;
- int cnt = canvas->line_cnt;
- _DtCvUnit width;
- /*
- * if line_width is zero, make it 1 so that it really takes
- * up some space.
- */
- if (0 == line_width)
- line_width = 1;
- /*
- * calculate the width of the element.
- */
- width = right_x - left_x;
- /*
- * If borders are specified, draw them
- */
- if (brdr != _DtCvBORDER_NONE)
- {
- /*
- * now do the horizontal borders. the coordinates are the top,
- * left most unit of the line.
- */
- switch(brdr)
- {
- case _DtCvBORDER_FULL:
- case _DtCvBORDER_HORZ:
- case _DtCvBORDER_BOTTOM:
- case _DtCvBORDER_BOTTOM_LEFT:
- case _DtCvBORDER_BOTTOM_RIGHT:
- SaveLine(canvas, layout, _DtCvLINE_HORZ,
- data, line_width,
- left_x, bot_y, width);
- mod = -1;
- if (brdr == _DtCvBORDER_BOTTOM
- || brdr == _DtCvBORDER_BOTTOM_LEFT
- || brdr == _DtCvBORDER_BOTTOM_RIGHT)
- break;
-
- case _DtCvBORDER_TOP:
- case _DtCvBORDER_TOP_LEFT:
- case _DtCvBORDER_TOP_RIGHT:
- SaveLine(canvas, layout, _DtCvLINE_HORZ,
- data, line_width,
- left_x, top_y, width);
- }
-
- /*
- * for vertical lines, the coordinates are the top, right most
- * unit of the line.
- */
- switch(brdr)
- {
- case _DtCvBORDER_FULL:
- case _DtCvBORDER_BOTTOM_LEFT:
- /*
- * include the line width in length for a full
- * border.
- */
- bot_y += line_width;
- case _DtCvBORDER_VERT:
- case _DtCvBORDER_LEFT:
- case _DtCvBORDER_TOP_LEFT:
- SaveLine(canvas, layout, _DtCvLINE_VERT,
- data, line_width,
- left_x, top_y, bot_y - top_y);
- if (brdr == _DtCvBORDER_LEFT
- || brdr == _DtCvBORDER_TOP_LEFT
- || brdr == _DtCvBORDER_BOTTOM_LEFT)
- break;
-
- case _DtCvBORDER_BOTTOM_RIGHT:
- /*
- * if we didn't fall thru from above, we need to
- * add the extension to the bottom to get the
- * full length for the right vertical line.
- */
- if (brdr == _DtCvBORDER_BOTTOM_RIGHT)
- bot_y += line_width;
- case _DtCvBORDER_RIGHT:
- case _DtCvBORDER_TOP_RIGHT:
- SaveLine(canvas, layout, _DtCvLINE_VERT,
- data, line_width,
- right_x - line_width, top_y, bot_y - top_y);
- }
- }
- return ((canvas->line_cnt - cnt) * mod);
- }
- /******************************************************************************
- * Function: AdjustObjectPosition
- *
- * Parameters:
- * canvas Specifies the virtual canvas on which
- * lines are drawn.
- * justify Specifies the vertical adjustment for the
- * object.
- * start_txt Specifies the start index of the text list.
- * start_gr Specifies the start index of the graphics list.
- * start_ln Specifies the start index of the line list.
- * end_txt Specifies the end indext of the text list.
- * end_gr Specifies the end indext of the graphics list.
- * end_ln Specifies the end indext of the line list.
- * height_adj Specifies the internal height adjust value.
- * Depending on the justify type, this may
- * add to y_adj for text and regions, bottom
- * lines and the height of vertical lines.
- * y_adj Specifies the y position adjustment.
- * Lines, text and regions are moved this
- * amount.
- * internal_y Specifies the internal y position adjustment.
- * height_adj includes this value. Text and
- * regions are moved this amount.
- *
- * Return: nothing.
- *
- *****************************************************************************/
- static void
- AdjustObjectPosition(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvFrmtOption justify,
- int start_txt,
- int start_ln,
- int start_brk,
- int end_txt,
- int end_ln,
- int end_brk,
- int brdr_cnt,
- _DtCvUnit height_adj,
- _DtCvUnit x_adj,
- _DtCvUnit y_adj,
- _DtCvUnit internal_y)
- {
- int mod = 1;
- _DtCvUnit yOff = 0;
- /*
- * If border count is negative, indicates the first line in the
- * list is bottom line. This requires special handling in adjusting
- * its position. Set flags accordingly.
- */
- if (brdr_cnt < 0)
- {
- mod = -1;
- brdr_cnt = -brdr_cnt;
- }
- /*
- * calculate the offset value within the object for other objects
- * contained in this object.
- */
- if (justify != _DtCvJUSTIFY_TOP)
- {
- yOff = height_adj - internal_y;
- if (justify == _DtCvJUSTIFY_CENTER)
- yOff /= 2;
- }
-
- yOff += y_adj;
- yOff += internal_y;
- /*
- * don't modify the border lines around this object yet.
- */
- end_ln -= brdr_cnt;
- /*
- * modify the border lines of the objects contained within
- * this object.
- */
- AdjustLinePositions(canvas, start_ln, end_ln, x_adj, yOff);
- /*
- * now adjust the border lines around this object.
- */
- start_ln = end_ln;
- end_ln += brdr_cnt;
- AdjustLinePositions(canvas, start_ln, end_ln, x_adj, y_adj);
- /*
- * now fix the lines if they've changed height and move
- * the first line to its bottom position if necessary.
- */
- if (0 != height_adj)
- {
- while (start_ln < end_ln)
- {
- /*
- * indicates the bottom line is the first line in the
- * list. Move it down the height adjustment.
- */
- if (mod < 0)
- {
- canvas->line_lst[start_ln].pos_y += height_adj;
- canvas->line_lst[start_ln].max_y += height_adj;
- mod = 1;
- }
- /*
- * stretch the vertical lines
- */
- else if (canvas->line_lst[start_ln].dir == _DtCvLINE_VERT)
- canvas->line_lst[start_ln].max_y += height_adj;
- start_ln++;
- }
- }
- /*
- * adjust the position of the text within this object.
- */
- AdjustTextPositions (canvas, start_txt, end_txt, x_adj, yOff);
- /*
- * adjust the position of the text within this object.
- */
- AdjustPgBrk (canvas, start_brk, end_brk, yOff);
- }
- /******************************************************************************
- * Function: LinesMayChange
- *
- * Parameters:
- * canvas Specifies the virtual canvas on which
- * lines are drawn.
- * start_ln Specifies the start index of the line list.
- * end_ln Specifies the end indext of the line list.
- *
- * Return: True if there is a vertical line as a child of a container.
- * False if there are no vertical lines in the child of a
- * container/cell.
- *
- *****************************************************************************/
- static _DtCvValue
- LinesMayChange(
- _DtCanvasStruct *canvas,
- int start_ln,
- int end_ln,
- int brdr_cnt)
- {
- /*
- * If border count is negative, indicates that one of the lines
- * is for the bottom of the container/cell. Ignore for now.
- * we want to check the lines in the container/cell.
- */
- if (brdr_cnt < 0)
- brdr_cnt = -brdr_cnt;
- /*
- * get rid of the line count for this object,
- * AdjustObjectPosition can take care of it.
- */
- end_ln -= brdr_cnt;
- /*
- * Now check for vertical lines that would
- * be affected by a height change.
- */
- while (start_ln < end_ln)
- {
- if (_DtCvLINE_VERT == canvas->line_lst[start_ln].dir)
- return True;
- start_ln++;
- }
- return False;
- }
- /******************************************************************************
- * Function: ProcessContainer
- *
- * Initializes the display line and graphic tables.
- *****************************************************************************/
- static void
- ProcessContainer(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *con_seg,
- _DtCvUnit min_y,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_max_x,
- int *ret_cnt)
- {
- int getLn;
- const char *saveJustifyChar = layout->info.align_char;
- _DtCvUnit yPad = 0;
- _DtCvUnit xPad = 0;
- _DtCvUnit maxWidth = 0;
- _DtCvUnit maxXPos = 0;
- _DtCvUnit myMinY = -1;
- _DtCvUnit saveLeft = layout->left;
- _DtCvUnit saveRight = layout->right;
- _DtCvUnit saveLead = layout->info.leading;
- _DtCvUnit saveFirst = layout->first;
- _DtCvUnit saveYpos = layout->info.y_pos;
- _DtCvValue saveStatic = layout->stat_flag;
- _DtCvValue saveBrdr = layout->brdr_flag;
- _DtCvFrmtOption saveJustify = layout->txt_justify;
- LayFrmtInfo frmtInfo;
- DataPoint basePt;
- DataPoint curPt;
- /*
- * check to see if this element breaks the formatting sequence.
- * If so save any information in the buffer, reset the margins and
- * add the appropriate lines, and check for going over boundaries.
- */
- if (NotJoining(layout))
- {
- CheckSaveInfo(canvas, layout, con_seg, 0);
- CheckFormat(layout, True);
- }
- /*
- * check to see if this segment is the segment we want as our first
- * visible line.
- */
- CheckId(layout, _DtCvContainerIdOfSeg(con_seg));
- /*
- * Set beginning text and line counts
- */
- frmtInfo = DefLayFrmtInfo;
- SetBeginCounts(canvas, &(frmtInfo.cnt));
- /*
- * Get the first indent and set the current container pointer to me.
- */
- layout->first = _DtCvContainerFMarginOfSeg(con_seg) / layout->divisor;
- layout->left = _DtCvContainerLMarginOfSeg(con_seg) / layout->divisor;
- layout->right = _DtCvContainerRMarginOfSeg(con_seg) / layout->divisor;
- layout->info.leading = _DtCvContainerLeadingOfSeg(con_seg);
- /*
- * check to see if we violate the horiz_pad_hint on the left, right or
- * first margins.
- */
- if (canvas->metrics.horiz_pad_hint > _DtCvContainerLMarginOfSeg(con_seg))
- layout->left = _DtCvContainerLMarginOfSeg(con_seg);
- else if (layout->left < canvas->metrics.horiz_pad_hint)
- layout->left = canvas->metrics.horiz_pad_hint;
- if (canvas->metrics.horiz_pad_hint > _DtCvContainerRMarginOfSeg(con_seg))
- layout->right = _DtCvContainerRMarginOfSeg(con_seg);
- else if (layout->right < canvas->metrics.horiz_pad_hint)
- layout->right = canvas->metrics.horiz_pad_hint;
- if (canvas->metrics.horiz_pad_hint > _DtCvContainerFMarginOfSeg(con_seg))
- layout->first = _DtCvContainerFMarginOfSeg(con_seg);
- else if (layout->first < canvas->metrics.horiz_pad_hint)
- layout->first = canvas->metrics.horiz_pad_hint;
- /*
- * check to see if there is more squeeze room available.
- */
- if (layout->left > canvas->metrics.horiz_pad_hint
- || layout->right > canvas->metrics.horiz_pad_hint
- || layout->first > canvas->metrics.horiz_pad_hint)
- layout->margin_non_zero = True;
- /*
- * set the formatting type for this container
- */
- layout->stat_flag = False;
- if (_DtCvContainerTypeOfSeg(con_seg) == _DtCvLITERAL)
- layout->stat_flag = True;
- /*
- * check to see if this element breaks the formatting sequence.
- * If so, add lines, etc.
- */
- if (NotJoining(layout))
- {
- /*
- * Adjust margins and y position for bordering
- */
- AdjustForBorders (canvas, layout, Border(con_seg), BrdWidth(con_seg),
- &yPad, &xPad);
- _DtCvAddSpace(_DtCvContainerTMarginOfSeg(con_seg),
- &(layout->info.y_pos));
- /*
- * check for flow limits.
- */
- CheckFormat(layout, True);
- /*
- * get the parent's data point in the stack
- * and add the current container's left and right to it.
- */
- GetCurrentDataPoint(layout, &basePt);
- basePt.left += saveLeft;
- basePt.right += saveRight;
- /*
- * if we don't inherit the the text justification
- * set the new value.
- */
- if (_DtCvINHERIT != _DtCvContainerJustifyOfSeg(con_seg))
- {
- layout->txt_justify = _DtCvContainerJustifyOfSeg(con_seg);
- if (_DtCvJUSTIFY_NUM == layout->txt_justify)
- layout->info.align_char = PeriodStr;
- else if (_DtCvJUSTIFY_CHAR == layout->txt_justify)
- {
- layout->info.align_char = _DtCvContainerJustifyCharOfSeg(con_seg);
- /*
- * check to see if the character is 'valid'.
- * if not, default out of JUSTIFY_CHAR
- */
- if (NULL != layout->info.align_char ||
- '\0' == layout->info.align_char)
- layout->txt_justify = _DtCvJUSTIFY_LEFT;
- }
- }
- /*
- * terminate the previous rendering list
- */
- if (NULL != layout->lst_rendered)
- layout->lst_rendered->next_disp = NULL;
- layout->lst_rendered = NULL;
- /*
- * push the data point and reset margin/text info.
- */
- PushDataPoint(layout, &basePt);
- SetMargins(layout);
- SetTextPosition(layout, True);
- }
- /*
- * determine the minimum Y that the child of this container should
- * occupy. To do so, subtract off the bottom border pad and the
- * bottom margin.
- */
- if (0 < min_y)
- {
- myMinY = min_y - yPad;
- if (_DtCvWRAP_JOIN != _DtCvContainerFlowOfSeg(con_seg))
- {
- _DtCvUnit bPad = 0;
- _DtCvAddSpace(_DtCvContainerBMarginOfSeg(con_seg), &bPad);
- myMinY -= bPad;
- }
- }
- /*
- * format the segment
- */
- saveYpos = layout->info.y_pos;
- GetCurrentDataPoint(layout, &curPt);
- /*
- * reset the max x variable
- */
- layout->info.cur_max_x = 0;
- ProcessSegmentList(canvas, layout, _DtCvContainerListOfSeg(con_seg),
- myMinY,
- &maxWidth, &maxXPos, NULL);
- /*
- * if this container forces a wrap join of the next item,
- * save the current line, but don't add space or null the
- * last rendered item.
- */
- CheckSaveInfo(canvas, layout, con_seg, 0);
- if (maxWidth < layout->info.cur_max_x - curPt.left + layout->right)
- maxWidth = layout->info.cur_max_x - curPt.left + layout->right;
- if (maxXPos < layout->info.cur_max_x)
- maxXPos = layout->info.cur_max_x;
- if (_DtCvWRAP_JOIN != _DtCvContainerFlowOfSeg(con_seg))
- {
- /*
- * Save any information in the buffer,
- * reset the margins and add the appropriate lines,
- * and check for going over boundaries.
- */
- _DtCvAddSpace(_DtCvContainerBMarginOfSeg(con_seg),
- &(layout->info.y_pos));
- /*
- * terminate the previous rendering list
- */
- if (NULL != layout->lst_rendered)
- layout->lst_rendered->next_disp = NULL;
- layout->lst_rendered = NULL;
- }
- /*
- * remove this element's data points from the stack.
- */
- RemoveDataPoint(layout, &basePt);
- /*
- * include the bottom border (if needed) in the ending y position
- */
- layout->info.y_pos += yPad;
- /*
- * Set the ending counts for the lines and text in me.
- * This sets the ending counts for the lines contained in me,
- * NOT the lines in my border.
- */
- SetEndCounts(canvas, &(frmtInfo.cnt), 0);
- /*
- * does this object need to be adjust within its height?
- */
- if (0 < min_y && layout->info.y_pos < min_y)
- {
- AdjustObjectPosition(canvas, layout, TxtVertJustify(con_seg),
- frmtInfo.cnt.beg_txt, frmtInfo.cnt.beg_ln,
- frmtInfo.cnt.beg_brk,
- frmtInfo.cnt.end_txt, frmtInfo.cnt.end_ln,
- frmtInfo.cnt.end_brk,
- 0, min_y - layout->info.y_pos - yPad, 0, 0, 0);
- layout->info.y_pos = min_y;
- }
- /*
- * Now draw the borders
- * If borders are drawn, cur_max_x & max_x_pos may get changed
- * if a right side border is drawn.
- */
- if (maxWidth < layout->max_width - curPt.left - curPt.right)
- maxWidth = layout->max_width - curPt.left - curPt.right;
- getLn = DrawBorders (canvas, layout, Border(con_seg),
- BrdData(con_seg), BrdWidth(con_seg),
- saveYpos, layout->info.y_pos - yPad,
- curPt.left,
- curPt.left + maxWidth);
- /*
- * check to see if we need to save the container counts away
- * because we might need to move the entire container as one
- * to honor the boundary. This will occur if the flag to honor
- * a boundary is set to _DtCvUSE_BOUNDARY_MOVE, this container has
- * border lines, the container's parent is not a table nor
- * is the container within another container that has a border.
- */
- if (_DtCvUSE_BOUNDARY_MOVE == canvas->constraint
- && True == layout->brdr_flag
- && False == saveBrdr && False == layout->table_flag)
- {
- GrpInfo *info = (GrpInfo *) malloc (sizeof(GrpInfo));
- /*
- * warning - nothing done if malloc error.
- */
- if (NULL != info)
- {
- /*
- * initialize to the end information of the container.
- */
- info->cnt = frmtInfo.cnt;
- /*
- * take into account the borders for this container
- */
- SetEndCounts(canvas, &(info->cnt), getLn);
- /*
- * set the linked list information
- */
- info->next_info = layout->grp_lst;
- layout->grp_lst = info;
- }
- }
- /*
- * set the return values.
- */
- *ret_max_x = layout->info.cur_max_x;
- *ret_width = maxWidth;
- if (*ret_width < layout->max_width - curPt.left - curPt.right)
- *ret_width = layout->max_width - curPt.left - curPt.right;
- /*
- * Restore the previous information
- */
- layout->left = saveLeft;
- layout->right = saveRight;
- layout->first = saveFirst;
- layout->stat_flag = saveStatic;
- layout->brdr_flag = saveBrdr;
- layout->info.leading = saveLead;
- /*
- * Besides checking for flow constraints, also (re)sets margins and
- * text information.
- */
- CheckFormat(layout, True);
- layout->txt_justify = saveJustify;
- layout->info.align_char = saveJustifyChar;
- /*
- * for tables and such, return how many lines were drawn around this
- * container.
- */
- if (ret_cnt)
- *ret_cnt = getLn;
- return;
- }
- /******************************************************************************
- * Function: ProcessSegmentList
- *
- * Process the segment list, laying it out according to left, right,
- * and first margins specified. Returns the max_width of the all
- * segments processed and the maximum x coordinate used.
- *****************************************************************************/
- static void
- ProcessSegmentList(
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvSegmentI *cur_seg,
- _DtCvUnit min_y,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_max_x,
- int **ret_vert)
- {
- int junk;
- int saveTravCnt = canvas->trav_cnt;
- int saveTxtCnt = canvas->txt_cnt;
- int saveLineCnt = canvas->line_cnt;
- int saveBrkCnt = canvas->brk_cnt;
- _DtCvUnit tempX;
- _DtCvUnit tempLen;
- _DtCvUnit width;
- _DtCvUnit nWidth = 0;
- _DtCvUnit leftMargin = 0;
- _DtCvUnit rightMargin = 0;
- _DtCvUnit topHeight = 0;
- _DtCvUnit botHeight = 0;
- _DtCvUnit maxWidth = 0;
- _DtCvUnit saveYpos = layout->info.y_pos;
- _DtCvSegmentI *segStart = cur_seg;
- LayFrmtInfo *headInfo = NULL;
- LayFrmtInfo *lastHead = NULL;
- LayFrmtInfo *nxtHead;
- _DtCvLayoutInfo startInfo;
- _DtCvValue redo = False;
- _DtCvValue joinCleared = False;
- _DtCvValue flag;
- TopDims topBot;
- SideDims sideDims;
- CornerDims cornerDims;
- FlowDims flowDims;
- DataPoint basePt;
- DataPoint leftPt;
- DataPoint rightPt;
- /*
- * clear the controller arrays
- */
- InitDimArrays(&topBot, &sideDims, &cornerDims, &flowDims);
- /*
- * get the current left and right values or 'base'.
- */
- GetCurrentDataPoint(layout, &basePt);
- /*
- * ???
- */
- leftPt = basePt;
- rightPt = basePt;
- leftPt.y_pos = _CEFORMAT_ALL;
- rightPt.y_pos = _CEFORMAT_ALL;
- /*
- * process all the controller type containers in the segment list
- */
- while (NULL != cur_seg)
- {
- if (_DtCvIsSegContainer(cur_seg) && _DtCvIsSegController(cur_seg))
- {
- /*
- * want to clear this once and only once. Then any join
- * directives will survive, though if two or more controllers
- * have the directive set, the 'last' one will win out.
- */
- if (False == joinCleared)
- {
- _DtCvSetJoinInfo(&(layout->info), False, -1);
- joinCleared = True;
- }
- /*
- * process the 'controller'
- */
- nxtHead = ProcessController(canvas, layout, cur_seg);
- /*
- * update the dimension arrays so that the controller
- * will get placed correctly.
- */
- UpdateDimensionArrays(cur_seg, nxtHead->width, nxtHead->height,
- &topBot, &sideDims, &cornerDims, &flowDims,
- &leftMargin, &rightMargin);
- /*
- * remember this controller.
- */
- if (NULL == headInfo)
- headInfo = nxtHead;
- else
- lastHead->next_info = nxtHead;
- lastHead = nxtHead;
- }
- /*
- * go to the next segment
- */
- cur_seg = cur_seg->next_seg;
- }
- /*
- * Now reset the margins based on the controllers found
- */
- if (NULL != headInfo)
- {
- DetermineMaxDims(&topBot, &cornerDims, leftMargin, rightMargin,
- &topHeight, &botHeight, &maxWidth);
- layout->info.y_pos += topHeight;
- layout->left += leftMargin;
- layout->right += rightMargin;
- DetermineFlowConstraints(layout, flowDims,
- basePt.left, basePt.right,
- layout->info.y_pos, &leftPt, &rightPt);
- /*
- * get rid of the leftMargin and rightMargin values in maxWidth
- * otherwise the use of layout->left & layout->right will double
- * the value.
- */
- maxWidth = maxWidth - leftMargin - rightMargin;
- if (layout->max_width < maxWidth + basePt.left + basePt.right +
- layout->left + layout->right)
- layout->max_width = maxWidth + basePt.left + basePt.right +
- layout->left + layout->right;
- SetMargins(layout);
- SetTextPosition(layout, True);
- if (JoinSet(layout))
- {
- int cnt;
- int joinLine = layout->info.join_line;
- int start = canvas->txt_lst[joinLine].byte_index;
- int count = canvas->txt_lst[joinLine].length;
- _DtCvSegmentI *pSeg = canvas->txt_lst[joinLine].seg_ptr;
- _DtCvUnit tmpWidth;
- /*
- * change the starting location of the following text.
- * take into account the left margin that *hasn't*
- * been added to the controlling container.
- */
- layout->info.text_x_pos = canvas->txt_lst[joinLine].text_x
- + layout->lmargin;
- layout->info.cur_len = 0;
- /*
- * now calculate the width of this line.
- */
- while (pSeg != NULL && count > 0)
- {
- _DtCvGetWidthOfSegment(canvas,pSeg,start,count,
- &cnt, &tmpWidth, NULL);
- layout->info.text_x_pos += tmpWidth;
- count -= cnt;
- start = 0;
- pSeg = pSeg->next_disp;
- }
- }
- }
- /*
- * now format for non-controller containers and non-containers.
- * re-start at the beginning.
- */
- cur_seg = segStart;
- /*
- * Save some information incase we have to redo the layout. I.e.
- * we overflow the sizing.
- */
- startInfo = layout->info;
- saveTravCnt = canvas->trav_cnt;
- saveTxtCnt = canvas->txt_cnt;
- saveLineCnt = canvas->line_cnt;
- saveBrkCnt = canvas->brk_cnt;
- while (NULL != cur_seg)
- {
- width = layout->max_width - layout->info.text_x_pos
- - layout->rmargin - layout->info.cur_len;
- /*
- * check to see if this item should start a line.
- */
- CheckSetLineStart(layout, cur_seg);
- /*
- * check to see if this item will cause a page break.
- */
- CheckForPageBreak(canvas, cur_seg, layout->info.y_pos);
- switch (_DtCvPrimaryTypeOfSeg(cur_seg))
- {
- case _DtCvCONTAINER:
- if (!(_DtCvIsSegController(cur_seg)))
- ProcessContainer(canvas, layout, cur_seg, min_y,
- &junk, &junk, &junk);
- break;
- case _DtCvREGION:
- /*
- * flag that this segment needs a line number
- */
- cur_seg->internal_use = (void *) -1;
- /*
- * process the segment
- */
- if (_DtCvIsSegInLine(cur_seg))
- {
- /*
- * if a hypertext link, this will add it to
- * the internal list.
- */
- CheckAddToHyperList(canvas, cur_seg);
- /*
- * get the traversal width
- */
- nWidth = _DtCvGetTraversalWidth(canvas, cur_seg,
- layout->info.lst_hyper);
- /*
- * check to see if this region can end a line
- */
- flag = _DtCvCheckLineSyntax(canvas,cur_seg,0,0,False);
- /*
- * if this can't end a line, get the length up to
- * the next segment that can and base whether to
- * save pased on that.
- */
- tempLen = 0;
- if (False == flag)
- {
- tempLen = _DtCvGetNextWidth(canvas,
- _DtCvSTRING,
- layout->info.lst_hyper,
- cur_seg->next_seg,
- 0, cur_seg, NULL, NULL, NULL);
- /*
- * if the next width is zero, reset the flag.
- */
- if (tempLen <= 0)
- flag = True;
- }
- tempLen += nWidth;
- /*
- * if not joining, but my length goes over the
- * working width, save out the current buffered
- * information
- */
- if (NotJoining(layout) &&
- _DtCvWidthOfRegionSeg(cur_seg) + tempLen > width)
- CheckSaveInfo (canvas, layout, cur_seg, 0);
- /*
- * up counts on the buffered information.
- */
- layout->info.line_bytes += 1;
- layout->info.cur_len +=
- (_DtCvWidthOfRegionSeg(cur_seg) + nWidth);
- /*
- * does the next segment need to join with
- * this one? If so, set the information
- */
- _DtCvSetJoinInfo(&(layout->info), (flag ? 0 : 1), -1);
- if (_DtCvIsSegNewLine(cur_seg))
- SaveInfo(canvas, layout, cur_seg, 0);
- }
- else
- {
- /*
- * clear out the join information
- * standalone figures can't join with others.
- */
- _DtCvSetJoinInfo(&(layout->info), False, -1);
- /*
- * figures are standalone. Save any
- * information in the buffer away.
- */
- CheckSaveInfo (canvas, layout, cur_seg, 0);
- /*
- * check to see if this segment is
- * a hypertext. If so, add it to the
- * list if it hasn't been added yet.
- */
- CheckAddToHyperList(canvas, cur_seg);
- /*
- * get the traversal width, if any.
- */
- nWidth = _DtCvGetTraversalWidth(canvas, cur_seg,
- layout->info.lst_hyper);
- /*
- * now save the standalone figure
- */
- layout->info.line_bytes += 1;
- layout->info.cur_len +=
- _DtCvWidthOfRegionSeg(cur_seg) + nWidth;
- SaveInfo(canvas, layout, cur_seg->next_seg, 0);
- /*
- * check for wrapping overflow
- */
- CheckFormat(layout, False);
- }
- /*
- * indicate this segment as the last item rendered
- */
- if (NULL != layout->lst_rendered)
- layout->lst_rendered->next_disp = cur_seg;
- layout->lst_rendered = cur_seg;
- break;
- case _DtCvLINE:
- /*
- * lines are standalone. Save any
- * information in the buffer away.
- */
- CheckSaveInfo (canvas, layout, cur_seg, 0);
- /*
- * if the line_width is zero, make it 1 so
- * that it really does take some space.
- */
- nWidth = _DtCvWidthOfLineSeg(cur_seg);
- if (0 == nWidth)
- nWidth = 1;
- /*
- * start with it going all the way across the window.
- */
- width = layout->max_width;
- tempX = 0;
- /*
- * or does it only extend across the container?
- */
- if (_DtCvIsSegBlockLine(cur_seg))
- {
- tempX = layout->lmargin;
- width = layout->max_width - tempX - layout->rmargin;
- }
- SaveLine (canvas, layout, _DtCvLINE_HORZ,
- _DtCvDataOfLineSeg(cur_seg), nWidth, tempX,
- layout->info.y_pos, width);
- layout->info.y_pos += nWidth;
- break;
- case _DtCvMARKER:
- /*
- * check to see if marker is the target id
- */
- CheckId(layout, _DtCvIdOfMarkerSeg(cur_seg));
- break;
- case _DtCvNOOP:
- if (_DtCvIsSegNewLine(cur_seg))
- SaveInfo(canvas, layout, cur_seg, 0);
- break;
- case _DtCvSTRING:
- /*
- * flag that this segment needs a line number
- */
- cur_seg->internal_use = (void *) -1;
- /*
- * process the string
- */
- ProcessStringSegment(canvas, layout, cur_seg);
- /*
- * check for wrapping overflow.
- */
- if (_DtCvIsSegNewLine(cur_seg))
- CheckFormat(layout, False);
- /*
- * indicate this segment as the last item rendered
- */
- if (NULL != layout->lst_rendered)
- layout->lst_rendered->next_disp = cur_seg;
- layout->lst_rendered = cur_seg;
- break;
- case _DtCvTABLE:
- ProcessTable(canvas, layout, cur_seg, min_y);
- default:
- break;
- }
- /*
- * get the next segment
- */
- cur_seg = cur_seg->next_seg;
- /*
- * check the flowing text points
- */
- if (leftPt.y_pos > 0 &&
- leftPt.x_units > layout->max_width - leftPt.left - leftPt.right)
- {
- layout->max_width = leftPt.x_units + leftPt.left + leftPt.right;
- redo = True;
- }
- if (rightPt.y_pos > 0 &&
- rightPt.x_units > layout->max_width-rightPt.left-rightPt.right)
- {
- layout->max_width = rightPt.x_units + rightPt.left + rightPt.right;
- redo = True;
- }
- /*
- * have we violated the available space?
- * if so, we'll have to reformat.
- */
- if (redo == True)
- {
- redo = False;
- cur_seg = segStart;
- canvas->trav_cnt = saveTravCnt;
- canvas->txt_cnt = saveTxtCnt;
- canvas->line_cnt = saveLineCnt;
- canvas->brk_cnt = saveBrkCnt;
- layout->info = startInfo;
- if (rightPt.y_pos > 0)
- {
- RemoveDataPoint(layout, &rightPt); /* make sure its gone */
- InsertDataPoint(layout, &rightPt);
- }
- if (leftPt.y_pos > 0)
- {
- RemoveDataPoint(layout, &leftPt); /* make sure its gone */
- InsertDataPoint(layout, &leftPt);
- }
- /*
- * Now reset the margins based on the controllers found
- */
- if (NULL != headInfo)
- {
- layout->left += leftMargin;
- layout->right += rightMargin;
- SetMargins(layout);
- SetTextPosition(layout, True);
- if (JoinSet(layout))
- {
- int cnt;
- int joinLine = layout->info.join_line;
- int start = canvas->txt_lst[joinLine].byte_index;
- int count = canvas->txt_lst[joinLine].length;
- _DtCvSegmentI *pSeg = canvas->txt_lst[joinLine].seg_ptr;
- _DtCvUnit tmpWidth;
-
- /*
- * change the starting location of the following text.
- * take into account the left margin that *hasn't*
- * been added to the controlling container.
- */
- layout->info.text_x_pos = canvas->txt_lst[joinLine].text_x
- + layout->lmargin;
- layout->info.cur_len = 0;
-
- /*
- * now calculate the width of this line.
- */
- while (pSeg != NULL && count > 0)
- {
- _DtCvGetWidthOfSegment(canvas,pSeg,start,count,
- &cnt, &tmpWidth, NULL);
- layout->info.text_x_pos += tmpWidth;
- count -= cnt;
- start = 0;
- pSeg = pSeg->next_disp;
- }
- }
- }
- }
- }
- RemoveDataPoint(layout, &leftPt);
- RemoveDataPoint(layout, &rightPt);
- /*
- * if there were heads, now place them correctly.
- */
- if (NULL != headInfo)
- {
- _DtCvUnit blockHeight;
- _DtCvUnit blockWidth;
- /*
- * make sure all of the information in the body is saved out
- */
- CheckSaveInfo (canvas, layout, NULL, 0);
- /*
- * now calculate the non-controllers overall height.
- */
- blockHeight = layout->info.y_pos - saveYpos - topHeight;
- /*
- * now figure the head positions.
- */
- DetermineHeadPositioning(&topBot, &sideDims, &cornerDims, &flowDims,
- saveYpos, topHeight,
- blockHeight, &blockHeight);
- /*
- * if the maximum available space was exceeded by the text
- * calculate a new max width
- */
- if (layout->max_width < layout->info.cur_max_x + layout->right)
- layout->max_width = layout->info.cur_max_x + layout->right;
- blockWidth = layout->max_width - basePt.left - basePt.right
- - layout->left - layout->right;
- nxtHead = headInfo;
- cur_seg = segStart;
- while (cur_seg != NULL)
- {
- if (_DtCvIsSegContainer(cur_seg) && _DtCvIsSegController(cur_seg))
- {
- AdjustHeadPosition(canvas, layout, cur_seg,
- &topBot, &sideDims, &cornerDims, &flowDims, nxtHead,
- 0, basePt.left + layout->left - leftMargin, blockWidth,
- leftMargin, rightMargin);
- /*
- * go to the next head element
- */
- nxtHead = nxtHead->next_info;
- /*
- * free the information.
- */
- free(headInfo);
- headInfo = nxtHead;
- }
- /*
- * got to the next segment
- */
- cur_seg = cur_seg->next_seg;
- }
- if (layout->info.y_pos < saveYpos + topHeight + blockHeight)
- layout->info.y_pos = saveYpos + topHeight + blockHeight;
- layout->info.y_pos += botHeight;
- }
- /*
- * set the return values
- */
- *ret_width = layout->info.cur_max_x - basePt.left + layout->right;
- *ret_max_x = layout->info.cur_max_x;
- return;
- }
- /*****************************************************************************
- * Function: static _DtCvUnit MaxOfGroup (
- *
- * Purpose: Determine the maximum of a group.
- *****************************************************************************/
- static void
- MaxOfGroup (
- GrpInfo *group,
- _DtCvDspLine *text,
- _DtCvLineSeg *lines,
- _DtCvUnit max_x,
- _DtCvUnit max_y)
- {
- int i;
- /*
- * initialize
- */
- group->min_x = max_x;
- group->max_x = 0;
- group->top_y = max_y;
- group->bot_y = 0;
- /*
- * find the maximum of the group
- */
- for (i = group->cnt.beg_txt; i < group->cnt.end_txt; i++)
- {
- /*
- * check for min's and max's
- */
- if (group->min_x > text[i].text_x)
- group->min_x = text[i].text_x;
- if (group->max_x < text[i].max_x)
- group->max_x = text[i].max_x;
- if (group->top_y > text[i].baseline - text[i].ascent)
- group->top_y = text[i].baseline - text[i].ascent;
- if (group->bot_y < text[i].baseline + text[i].descent)
- group->bot_y = text[i].baseline + text[i].descent;
- /*
- * indicate that this line has been processed already
- */
- _DtCvSetProcessed(text[i]);
- }
- for (i = group->cnt.beg_ln; i < group->cnt.end_ln; i++)
- {
- /*
- * check for min's and max's
- */
- if (group->min_x > lines[i].pos_x)
- group->min_x = lines[i].pos_x;
- if (group->max_x < lines[i].max_x)
- group->max_x = lines[i].max_x;
- if (group->top_y > lines[i].pos_y)
- group->top_y = lines[i].pos_y;
- if (group->bot_y < lines[i].max_y)
- group->bot_y = lines[i].max_y;
- /*
- * indicate that this line has been processed already
- */
- _DtCvSetProcessed(lines[i]);
- }
- }
- /*****************************************************************************
- * Function: static _DtCvUnit TestSpacing (
- *
- * Parameters:
- *
- * Returns: True if the object is before (x wise) the test object.
- * False if the object is not before (x wise) the text object.
- *
- * Purpose:
- *
- *****************************************************************************/
- static _DtCvStatus
- TestSpacing (
- _DtCvUnit tst_top,
- _DtCvUnit tst_bot,
- _DtCvUnit tst_min,
- _DtCvUnit obj_top,
- _DtCvUnit obj_bot,
- _DtCvUnit obj_max,
- _DtCvUnit needed,
- _DtCvUnit min_space,
- _DtCvUnit *ret_amount)
- {
- _DtCvStatus result = False;
- /*
- * check to see if the object is to the left of the test object
- * to move and that it 'infringes' on the vertical
- * space of the test object.
- *
- * I.e. ----obj_top------
- * | | ----tst_top----
- * ----obj_bot------ | |
- * ----tst_bot----
- *
- * I.e. ----tst_top----
- * ----obj_top------- | |
- * | | ----tst_bot----
- * ----obj_bot-------
- *
- * I.e. ----obj_top------
- * | | ----tst_top----
- * | | | |
- * | | ----tst_bot----
- * ----obj_bot------
- *
- * I.e. ----tst_top----
- * ----obj_top------- | |
- * | | | |
- * ----obj_bot------- | |
- * ----tst_bot----
- */
- if (obj_max < tst_min
- && True == _DtCvCheckInfringement(tst_top, tst_bot, obj_top, obj_bot)
- && needed > tst_min - obj_max)
- {
- /*
- * okay, this infringes on the object's space.
- * truncate the amount of room there is to move the object
- */
- result = True;
- needed = tst_min - obj_max;
- /*
- * is the space between these two objects already squeezed
- * below the minimum allowed?
- */
- if (needed < min_space)
- needed = 0;
- else /* leave the minimum space between the objects */
- needed -= min_space;
- }
- *ret_amount = needed;
- return result;
- }
- /*****************************************************************************
- * Function: static void MoveLeft (
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose: Moves the object's rules/lines and text lines to the left.
- *
- *****************************************************************************/
- static void
- MoveLeft (
- _DtCanvasStruct *canvas,
- int beg_txt,
- int end_txt,
- int beg_ln,
- int end_ln,
- _DtCvUnit space)
- {
- int i;
- /*
- * bail now if nothing to do.
- */
- if (1 > space)
- return;
- /*
- * move each text/region line.
- */
- for (i = beg_txt; i < end_txt; i++)
- {
- canvas->txt_lst[i].text_x -= space;
- canvas->txt_lst[i].max_x -= space;
- }
- /*
- * move each line/rule.
- */
- for (i = beg_ln; i < end_ln; i++)
- {
- canvas->line_lst[i].pos_x -= space;
- canvas->line_lst[i].max_x -= space;
- }
- }
- /*****************************************************************************
- * Function: static _DtCvUnit CheckSpacing (
- *
- * Purpose: Check the spacing before an object and move any objects
- * before it to the left to make room.
- *
- *****************************************************************************/
- static _DtCvUnit
- CheckSpacing (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- GrpInfo *tst_grp,
- int txt_idx,
- int line_idx,
- _DtCvUnit top_y,
- _DtCvUnit bot_y,
- _DtCvUnit min_x,
- _DtCvUnit needed)
- {
- int i;
- _DtCvUnit space;
- _DtCvUnit maxSpace;
- _DtCvUnit topY;
- _DtCvUnit botY;
- GrpInfo *nxtGrp = layout->grp_lst;
- /*
- * truncate if the amount needed is more than available.
- */
- if (min_x < needed)
- needed = min_x;
- maxSpace = needed;
- /*
- * see what group is before this group and how much space there is
- */
- while (NULL != nxtGrp)
- {
- /*
- * as long as I'm not comparing against myself, try it.
- */
- if (nxtGrp != tst_grp)
- {
- /*
- * is this group before(x wise) the test group, infringing
- * upon the test group's top and bottom positioning (y)
- * and is the amount of space (x wise) between them smaller
- * than the current smallest space found?
- */
- if (True == TestSpacing (top_y, bot_y, min_x,
- nxtGrp->top_y, nxtGrp->bot_y,
- nxtGrp->max_x, needed,
- canvas->metrics.horiz_pad_hint,
- &space))
- {
- space += MoveGroup(canvas, layout, nxtGrp, needed - space);
- if (maxSpace > space)
- maxSpace = space;
- }
- }
- /*
- * check the next group
- */
- nxtGrp = nxtGrp->next_info;
- }
- /*
- * look at each of the text lines;
- */
- for (i = 0; i < canvas->txt_cnt; i++)
- {
- /*
- * Only look at those lines not already processed.
- */
- if (i != txt_idx && _DtCvIsNotProcessed(canvas->txt_lst[i]))
- {
- topY = canvas->txt_lst[i].baseline - canvas->txt_lst[i].ascent;
- botY = canvas->txt_lst[i].baseline - canvas->txt_lst[i].descent;
- if (True == TestSpacing(top_y, bot_y, min_x, topY, botY,
- canvas->txt_lst[i].max_x, needed,
- canvas->metrics.horiz_pad_hint, &space))
- {
- space += MoveText(canvas, layout, i, topY, botY, needed-space);
- if (maxSpace > space)
- maxSpace = space;
- }
- }
- }
- /*
- * look at each of the rules/lines;
- */
- for (i = 0; i < canvas->line_cnt; i++)
- {
- /*
- * Only look at those lines not already processed.
- */
- if (i != line_idx && _DtCvIsNotProcessed(canvas->line_lst[i]))
- {
- /*
- * calculate the top and bottom of the line
- */
- topY = canvas->line_lst[i].pos_y;
- botY = canvas->line_lst[i].max_y;
- if (True == TestSpacing(top_y, bot_y, min_x, topY, botY,
- canvas->line_lst[i].max_x, needed,
- canvas->metrics.horiz_pad_hint, &space))
- {
- space += MoveLines(canvas, layout, i, topY, botY, needed-space);
- if (maxSpace > space)
- maxSpace = space;
- }
- }
- }
- return maxSpace;
- }
- /*****************************************************************************
- * Function: static _DtCvUnit MoveGroup (_DtCanvasStruct canvas);
- *
- * Purpose: To move groupings (container, tables, etc.) as a group to
- * honor boundaries.
- *
- *****************************************************************************/
- static _DtCvUnit
- MoveGroup (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- GrpInfo *tst_grp,
- _DtCvUnit needed)
- {
- _DtCvUnit space;
- /*
- * find out what's in front of it. And how much 'extra' room
- * there is.
- */
- space = CheckSpacing(canvas, layout, tst_grp, -1, -1,
- tst_grp->top_y, tst_grp->bot_y, tst_grp->min_x,
- needed);
- /*
- * now move the group
- */
- MoveLeft(canvas, tst_grp->cnt.beg_txt, tst_grp->cnt.end_txt,
- tst_grp->cnt.beg_ln, tst_grp->cnt.end_ln, space);
- tst_grp->max_x -= space;
- tst_grp->min_x -= space;
- return space;
- }
- /*****************************************************************************
- * Function: static _DtCvUnit MoveText (_DtCanvasStruct canvas);
- *
- * Purpose: To move text lines to honor boundaries.
- *
- *****************************************************************************/
- static _DtCvUnit
- MoveText (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- int idx,
- _DtCvUnit top_y,
- _DtCvUnit bot_y,
- _DtCvUnit needed)
- {
- _DtCvUnit space;
- /*
- * find out what's in front of it. And how much 'extra' room
- * there is.
- */
- space = CheckSpacing(canvas, layout, NULL, idx, -1,
- top_y, bot_y,
- canvas->txt_lst[idx].text_x,
- needed);
- /*
- * now move the group
- */
- MoveLeft(canvas, idx, idx, -1, -1, space);
- return space;
- }
- /*****************************************************************************
- * Function: static _DtCvUnit MoveLines (_DtCanvasStruct canvas);
- *
- * Purpose: To move groupings (container, tables, etc.) as a group to
- * honor boundaries.
- *
- *****************************************************************************/
- static _DtCvUnit
- MoveLines (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- int idx,
- _DtCvUnit top_y,
- _DtCvUnit bot_y,
- _DtCvUnit needed)
- {
- _DtCvUnit space;
- /*
- * find out what's in front of it. And how much 'extra' room
- * there is.
- */
- space = CheckSpacing(canvas, layout, NULL, -1, idx,
- top_y, bot_y,
- canvas->line_lst[idx].pos_x,
- needed);
- /*
- * now move the group
- */
- MoveLeft(canvas, -1, -1, idx, idx, space);
- return space;
- }
- /*****************************************************************************
- * Function: static void CheckMoveInfo (_DtCanvasStruct canvas);
- *
- * Purpose: To move each of the groupings, rules and text lines to
- * honor boundaries.
- *
- *****************************************************************************/
- static void
- CheckMoveInfo (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout)
- {
- int i;
- _DtCvUnit topY;
- _DtCvUnit botY;
- _DtCvUnit maxWidth = canvas->metrics.width;
- GrpInfo *nxtGrp;
- /*
- * fill in the max x of each group
- */
- for (nxtGrp = layout->grp_lst; NULL != nxtGrp; nxtGrp = nxtGrp->next_info)
- {
- /*
- * find the maximum of the group
- */
- MaxOfGroup(nxtGrp, canvas->txt_lst, canvas->line_lst,
- layout->info.max_x_pos, layout->info.y_pos);
- }
- /*
- * now check each group for exceeding the boundary.
- */
- for (nxtGrp = layout->grp_lst; NULL != nxtGrp; nxtGrp = nxtGrp->next_info)
- {
- /*
- * does this group exceed the boundary?
- */
- if (maxWidth < nxtGrp->max_x)
- (void) MoveGroup(canvas, layout, nxtGrp, nxtGrp->max_x - maxWidth);
- }
- /*
- * look at each of the text lines;
- */
- for (i = 0; i < canvas->txt_cnt; i++)
- {
- /*
- * Only look at those lines not already processed.
- */
- if (_DtCvIsNotProcessed(canvas->txt_lst[i]) &&
- maxWidth < canvas->txt_lst[i].max_x)
- {
- topY = canvas->txt_lst[i].baseline - canvas->txt_lst[i].ascent;
- botY = canvas->txt_lst[i].baseline - canvas->txt_lst[i].descent;
- (void) MoveText(canvas, layout, i, topY, botY,
- canvas->txt_lst[i].max_x - maxWidth);
- }
- }
- /*
- * look at each of the rules/lines;
- */
- for (i = 0; i < canvas->line_cnt; i++)
- {
- /*
- * Only look at those lines not already processed.
- */
- if (_DtCvIsNotProcessed(canvas->line_lst[i]) &&
- maxWidth < canvas->line_lst[i].max_x)
- {
- /*
- * calculate the top and bottom of the line
- */
- topY = canvas->line_lst[i].pos_y;
- botY = canvas->line_lst[i].max_y;
- (void) MoveLines(canvas, layout, i, topY, botY,
- canvas->line_lst[i].max_x - maxWidth);
- }
- }
- }
- /*****************************************************************************
- * Function: static void CompareUnits ()
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- static int
- CompareUnits (
- const void *a,
- const void *b)
- {
- _DtCvUnit *aPtr = (_DtCvUnit *) a;
- _DtCvUnit *bPtr = (_DtCvUnit *) b;
- if (*aPtr < *bPtr) return -1;
- if (*aPtr == *bPtr) return 0;
- return 1;
- }
- /*****************************************************************************
- * Function: static void CompareSearchs ()
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- static int
- CompareSearchs (
- const void *a,
- const void *b)
- {
- _DtCvSearchData *searchA = (_DtCvSearchData *) a;
- _DtCvSearchData *searchB = (_DtCvSearchData *) b;
- _DtCvDspLine *lineA = &(searchA->lst[searchA->idx]);
- _DtCvDspLine *lineB = &(searchB->lst[searchB->idx]);
- _DtCvUnit topA = lineA->baseline - lineA->ascent;
- _DtCvUnit topB = lineB->baseline - lineB->ascent;
- _DtCvUnit heightA = lineA->ascent + lineA->descent;
- _DtCvUnit heightB = lineB->ascent + lineB->descent;
- _DtCvUnit centA = topA + (heightA >> 1);
- _DtCvUnit centB = topB + (heightB >> 1);
- if (lineA->baseline + lineA->descent < centB && centA < topB)
- return -1;
- if (lineB->baseline + lineB->descent < centA && centB < topA)
- return 1;
- if (lineA->text_x != lineB->text_x)
- return ((lineA->text_x < lineB->text_x) ? -1 : 1);
- if (topA != topB)
- return ((topA < topB) ? -1 : 1);
- if (heightA != heightB)
- return ((heightA < heightB) ? -1 : 1);
- if (lineA->max_x != lineB->max_x)
- return ((lineA->max_x < lineB->max_x) ? -1 : 1);
- return 0;
- }
- /*****************************************************************************
- * Function: static Status LayoutCanvasInfo (_DtCvHandle canvas);
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- static _DtCvStatus
- LayoutCanvasInfo (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- _DtCvUnit divisor,
- char *target_id)
- {
- int i = 0;
- DataPoint basePt;
- _DtCvUnit maxWidth = 0;
- _DtCvUnit maxXPos = 0;
- _DtCvStatus result = _DtCvSTATUS_OK;
- *layout = DefInfo;
- layout->divisor = divisor;
- layout->max_width = canvas->metrics.width;
- layout->left = canvas->metrics.side_margin;
- layout->right = canvas->metrics.side_margin;
- layout->target_id = target_id;
- _DtCvInitLayoutInfo(canvas, &(layout->info));
- basePt = DefDataPt;
- PushDataPoint(layout, &basePt);
- SetMargins (layout);
- SetTextPosition (layout, True);
- ProcessSegmentList(canvas, layout, canvas->element_lst, -1,
- &maxWidth, &maxXPos, NULL);
- RemoveDataPoint(layout, &basePt);
- /*
- * fill in the max_x of each line of text/regions.
- */
- for (i = 0; i < canvas->txt_cnt; i++)
- canvas->txt_lst[i].max_x = MaxXOfLine(canvas, &(canvas->txt_lst[i]));
- /*
- * calculate the actual right hand side boundary.
- */
- layout->info.max_x_pos += canvas->metrics.side_margin;
- /*
- * the max_x_pos so far has indicated where the *next* character,
- * line or region will be *started*. Therefore back up one to
- * indicate the true last position used.
- */
- layout->info.max_x_pos--;
- return result;
- } /* End LayoutCanvasInfo */
- /*****************************************************************************
- * Function: static Status LayoutCanvas (_DtCvHandle canvas);
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- static _DtCvStatus
- LayoutCanvas (
- _DtCanvasStruct *canvas,
- LayoutInfo *layout,
- char *target_id)
- {
- _DtCvUnit divisor = 1;
- _DtCvValue redo;
- _DtCvStatus result;
- int i, search_cnt = canvas->search_cnt;
-
- do {
- redo = False;
- result = LayoutCanvasInfo(canvas, layout, divisor, target_id);
- /*
- * Are we suppose to honor the boundary?
- * If so, do any lines go over the boundary?
- * Is there any margins that can be decremented?
- */
- if (_DtCvSTATUS_OK == result
- && (_DtCvUSE_BOUNDARY == canvas->constraint ||
- _DtCvUSE_BOUNDARY_MOVE == canvas->constraint)
- && layout->info.max_x_pos >= canvas->metrics.width)
- {
- if (_DtCvUSE_BOUNDARY_MOVE == canvas->constraint)
- {
- int i;
- /*
- * clear the processed flag from all the text/region lines.
- */
- for (i = 0; i < canvas->txt_cnt; i++)
- _DtCvClearProcessed(canvas->txt_lst[i]);
- /*
- * clear the processed flag from all the line/rules.
- */
- for (i = 0; i < canvas->line_cnt; i++)
- _DtCvClearProcessed(canvas->line_lst[i]);
- CheckMoveInfo(canvas, layout);
- /*
- * recalculate the new max x
- */
- layout->info.max_x_pos = 0;
- for (i = 0; i < canvas->txt_cnt; i++)
- if (layout->info.max_x_pos < canvas->txt_lst[i].max_x)
- layout->info.max_x_pos = canvas->txt_lst[i].max_x;
- for (i = 0; i < canvas->line_cnt; i++)
- if (layout->info.max_x_pos < canvas->line_lst[i].max_x)
- layout->info.max_x_pos = canvas->line_lst[i].max_x;
- layout->info.max_x_pos--;
- }
- else if (True == layout->margin_non_zero)
- {
- redo = True;
- divisor *= 2;
- canvas->txt_cnt = 0;
- canvas->line_cnt = 0;
- canvas->trav_cnt = 0;
- }
- }
- } while (True == redo);
- /*
- * clean up table information
- */
- if (NULL != layout->grp_lst)
- free(layout->grp_lst);
- /*
- * subtract one from the y position to indicate the *last*
- * pixel/column/etc that will be rendered.
- */
- canvas->max_y = layout->info.y_pos - 1;
- canvas->max_x = layout->info.max_x_pos;
- for (i = search_cnt; i < canvas->search_cnt; i++)
- {
- canvas->searchs[i - search_cnt] = canvas->searchs[i];
- canvas->searchs[i - search_cnt].lst = canvas->txt_lst;
- }
- canvas->search_cnt -= search_cnt;
- /*
- * are there any search hits?
- */
- if (0 != canvas->search_cnt)
- qsort (canvas->searchs, canvas->search_cnt, sizeof(_DtCvSearchData),
- CompareSearchs);
- /*
- * sort the page break list.
- */
- if (0 != canvas->brk_cnt)
- qsort (canvas->pg_breaks, canvas->brk_cnt, sizeof(_DtCvUnit),
- CompareUnits);
- return result;
- } /* End LayoutCanvas */
- /*****************************************************************************
- * Function: static void SortTraversal (_DtCvHandle canvas);
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- static void
- SortTraversal (_DtCanvasStruct *canvas)
- {
- int i;
- /*
- * sort the links correctly. First, establish the x,y,width,height
- * of each link.
- */
- for (i = 0; i < canvas->trav_cnt; i++)
- {
- if (_DtCvTraversalLink == canvas->trav_lst[i].type)
- GetLinkInfo(canvas, i, &(canvas->trav_lst[i].x_pos),
- &(canvas->trav_lst[i].y_pos),
- &(canvas->trav_lst[i].width),
- &(canvas->trav_lst[i].height));
- else
- _DtCvCalcMarkPos(canvas, canvas->trav_lst[i].idx,
- &(canvas->trav_lst[i].x_pos),
- &(canvas->trav_lst[i].y_pos),
- &(canvas->trav_lst[i].width),
- &(canvas->trav_lst[i].height));
- }
- _DtCvSortTraversalList(canvas, _DtCvFALSE);
- }
- /*****************************************************************************
- * Function: static void ProcessMarks (_DtCanvasStruct *canvas);
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- static _DtCvStatus
- ProcessMarks (
- _DtCanvasStruct *canvas,
- _DtCvPointInfo **mark_lst)
- {
- int markIdx;
- int result = _DtCvSTATUS_OK;
- _DtCvSelectData beg;
- _DtCvSelectData end;
- _DtCvSegmentI *firstSeg;
- while (NULL != mark_lst && NULL != *mark_lst)
- {
- /*
- * convert the segments to begin and end points
- */
- if (_DtCvSTATUS_BAD == _DtCvCvtSegsToPts(canvas, (*mark_lst)->segs,
- &beg, &end, NULL, NULL, &firstSeg))
- /*
- * just set a return value since this indicates bad data
- * and not system failure.
- */
- result = _DtCvSTATUS_BAD;
- /*
- * now add it to the mark list
- */
- else
- {
- markIdx = _DtCvAddToMarkList(canvas, (*mark_lst)->client_data,
- _DtCvFALSE, &beg, &end);
- /*
- * now put the mark in the traversal list, but don't sort
- * or fill out position and dimension information.
- * SortTraversal() will do that.
- *
- * bail here if system failure indicated.
- */
- if (-1 == markIdx || 0 != _DtCvSetTravEntryInfo(canvas,
- _DtCvGetNextTravEntry(canvas),
- _DtCvTraversalMark, firstSeg,
- markIdx, _DtCvTRUE))
- return _DtCvSTATUS_BAD;
- }
- mark_lst++;
- }
- return result;
- }
- /*****************************************************************************
- * Public Functions
- *****************************************************************************/
- /*****************************************************************************
- * Function: void _DtCanvasResize (_DtCvHandle canvas);
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- _DtCvStatus
- _DtCanvasResize (
- _DtCvHandle canvas_handle,
- _DtCvValue force,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_height )
- {
- int i;
- _DtCvStatus selectStatus;
- _DtCvStatus retStatus = _DtCvSTATUS_NONE;
- _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
- _DtCvUnit oldWidth = canvas->metrics.width;
- LayoutInfo layOut;
- _DtCvPointInfo selPt;
- _DtCvPointInfo **markInfo;
- selPt.client_data = NULL;
- selPt.segs = NULL;
- /*
- * check to see if the width has changed - if not,
- * don't do anything (but re-initialize the metrics
- * to get the new height).
- */
- (*(canvas->virt_functions.get_metrics))(canvas->client_data,
- _DtCvCANVAS_TYPE, &(canvas->metrics));
- if (canvas->metrics.width != oldWidth || _DtCvTRUE == force)
- {
- /*
- * remember the current selection.
- */
- selectStatus = _DtCanvasGetSelectionPoints(canvas, &(selPt.segs),
- NULL, NULL);
- /*
- * remember the marks
- */
- if (_DtCvSTATUS_BAD == _DtCvGetMarkSegs(canvas, &markInfo))
- return _DtCvSTATUS_BAD;
- /*
- * Re-Layout the information.
- * First step - invalidate some counters.
- */
- canvas->trav_cnt = 0; /* zero this only because we re-process */
- /* do not zero cur_hyper or we'll loose */
- /* where we are in the TOC */
- canvas->txt_cnt = 0;
- canvas->line_cnt = 0;
- canvas->mark_cnt = 0;
- canvas->brk_cnt = 0;
- /*
- * Layout the information if there is anything to do
- */
- if (_DtCvSTATUS_BAD == LayoutCanvas (canvas, &layOut, NULL))
- return _DtCvSTATUS_BAD;
-
- /*
- * restore the current selection.
- */
- if (_DtCvSTATUS_OK == selectStatus)
- {
- _DtCanvasActivatePts(canvas,_DtCvACTIVATE_SELECTION, &selPt,
- NULL,NULL);
- _DtCvFreeArray((void **) selPt.segs);
- }
- /*
- * now place the marks in the mark and traversal lists
- */
- ProcessMarks(canvas, markInfo);
- if (NULL != markInfo)
- {
- for (i = 0; NULL != markInfo[i]; i++)
- _DtCvFreeArray((void **) (markInfo[i]->segs));
- _DtCvFreeArray((void **) markInfo);
- }
- /*
- * sort the traversal list.
- */
- SortTraversal(canvas);
- retStatus = _DtCvSTATUS_OK;
- }
- /*
- * return the maximum height and width used
- */
- if (ret_width != NULL)
- *ret_width = canvas->max_x;
- if (ret_height != NULL)
- *ret_height = canvas->max_y;
- return retStatus;
- } /* End _DtCanvasResize */
- /*****************************************************************************
- * Function: void _DtCanvasSetTopic (_DtCvHandle canvas);
- *
- * Parameters:
- *
- * Returns:
- *
- * Purpose:
- *
- *****************************************************************************/
- _DtCvStatus
- _DtCanvasSetTopic (
- _DtCvHandle canvas_handle,
- _DtCvTopicPtr topic,
- _DtCvValue honor_size,
- _DtCvUnit *ret_width,
- _DtCvUnit *ret_height,
- _DtCvUnit *ret_y )
- {
- _DtCvStatus result = _DtCvSTATUS_OK;
- _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
- LayoutInfo layOut;
- /*
- * clean the canvas
- */
- _DtCanvasClean (canvas_handle);
- /*
- * attach to the canvas
- */
- canvas->element_lst = topic->seg_list;
- /*
- * Attach the link information
- */
- canvas->link_data = topic->link_data;
- /*
- * init the internal use pointer in all containers to NULL
- */
- _DtCvClearInternalUse(canvas->element_lst, _DtCvFALSE);
- /*
- * Layout the information if there is anything to do
- */
- canvas->constraint = honor_size;
- if (_DtCvSTATUS_BAD == LayoutCanvas (canvas, &layOut, topic->id_str))
- return _DtCvSTATUS_BAD;
-
- /*
- * add the marks to the mark and traversal lists
- */
- ProcessMarks(canvas, topic->mark_list);
- /*
- * sort the traversal list.
- */
- SortTraversal(canvas);
- /*
- * return the maximum height and width used
- * And the location of the id.
- */
- if (ret_width != NULL)
- *ret_width = canvas->max_x;
- if (ret_height != NULL)
- *ret_height = canvas->max_y;
- if (ret_y != NULL)
- {
- if (NULL != layOut.target_id && True != layOut.id_found)
- result = _DtCvSTATUS_ID_BAD;
- *ret_y = layOut.id_Ypos;
- }
- return result;
- } /* End _DtCanvasSetTopic */
|