12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: 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"
- /******************************************************************************
- *
- * 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 = 0;
- 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)
- {
- int i;
- char *id = NULL;
- char *idRefs;
- char *ptr = NULL;
- char c = 0;
- 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 = 0;
- 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)
- {
- 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 accommodate
- * 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)
- {
- 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 */
|