Layout.c 149 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these librararies and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: Layout.c /main/31 1996/10/25 12:00:15 cde-hp $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: Layout.c
  28. **
  29. ** Project: CDE Info System
  30. **
  31. ** Description: Lays out the information on a canvas.
  32. **
  33. ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
  34. **
  35. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  36. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  37. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  38. ** (c) Copyright 1993, 1994 Novell, Inc.
  39. **
  40. **
  41. ****************************************************************************
  42. ************************************<+>*************************************/
  43. /*
  44. * system includes
  45. */
  46. #include <stdlib.h>
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include <limits.h>
  50. /*
  51. * Canvas Engine includes
  52. */
  53. #include "CanvasP.h"
  54. #include "CanvasSegP.h"
  55. /*
  56. * private includes
  57. */
  58. #include "bufioI.h"
  59. #include "CanvasI.h"
  60. #include "CvStringI.h"
  61. #include "LayoutUtilI.h"
  62. #include "SelectionI.h"
  63. #include "VirtFuncsI.h"
  64. #ifdef NLS16
  65. #include <nl_types.h>
  66. #endif
  67. /******************************************************************************
  68. *
  69. * Private Macros
  70. *
  71. *****************************************************************************/
  72. #define ObjHorizOrient(x) (_DtCvContainerOrientOfSeg(x))
  73. #define ObjVertOrient(x) (_DtCvContainerVOrientOfSeg(x))
  74. #define TxtHorizJustify(x) (_DtCvContainerJustifyOfSeg(x))
  75. #define TxtVertJustify(x) (_DtCvContainerVJustifyOfSeg(x))
  76. #define Border(x) (_DtCvContainerBorderOfSeg(x))
  77. #define BrdWidth(x) (_DtCvContainerLineWidthOfSeg(x))
  78. #define BrdData(x) (_DtCvContainerLineDataOfSeg(x))
  79. #define NotJoining(x) (False == (x)->info.join)
  80. #define JoinSet(x) (True == (x)->info.join)
  81. #define CheckAddToHyperList(a, b) \
  82. _DtCvCheckAddHyperToTravList(a, b, _DtCvTRUE, \
  83. &(layout->info.lst_vis), \
  84. &(layout->info.lst_hyper), &(layout->info.cur_len))
  85. /*****************************************************************************
  86. * Private Defines
  87. *****************************************************************************/
  88. /*
  89. * Defines for the dimension arrays
  90. */
  91. #define DIMS_LEFT 0
  92. #define DIMS_RIGHT 1
  93. #define DIMS_LM 0
  94. #define DIMS_CENTER 1
  95. #define DIMS_RM 2
  96. #define DIMS_TOP 0
  97. #define DIMS_BOTTOM 2
  98. #define DIMS_WIDTH 0
  99. #define DIMS_HEIGHT 1
  100. #define DIMS_YPOS 1
  101. #define DIMS_TC 0
  102. #define DIMS_BC 1
  103. /*
  104. */
  105. #define GROW_SIZE 10
  106. /******************************************************************************
  107. *
  108. * Private typedefs
  109. *
  110. *****************************************************************************/
  111. /*
  112. * top/bottom dimension array
  113. * -------------------------------------------
  114. * / DIMS_HEIGHT / DIMS_HEIGHT / DIMS_HEIGHT /|
  115. * / DIMS_YPOS / DIMS_YPOS / DIMS_YPOS / |
  116. * /-------------/-------------/-------------/ |
  117. * / DIMS_WIDTH / DIMS_WIDTH / DIMS_WIDTH /| /|
  118. * --------------|-------------|-------------| |/ |
  119. * DIMS_TOP | DIMS_LM | DIMS_CENTER | DIMS_RM | | /|
  120. * |-------------|-------------|-------------|/|/ |
  121. * unused | | | | | /
  122. * |-------------|-------------|-------------|/|/
  123. * DIMS_BOTTOM | DIMS_LM | DIMS_CENTER | DIMS_RM | /
  124. * ------------------------------------------|/
  125. */
  126. typedef _DtCvUnit TopDims[DIMS_BOTTOM+1][DIMS_RM+1][DIMS_HEIGHT+1];
  127. /*
  128. * left/right side dimension array - contains only the height or y_pos.
  129. * ----------------------------
  130. * DIMS_TOP | DIMS_LEFT | DIMS_RIGHT |
  131. * |------------|-------------|
  132. * DIMS_CENTER | DIMS_LEFT | DIMS_RIGHT |
  133. * |------------|-------------|
  134. * DIMS_BOTTOM | DIMS_LEFT | DIMS_RIGHT |
  135. * ----------------------------
  136. */
  137. typedef _DtCvUnit SideDims[DIMS_BOTTOM+1][DIMS_RIGHT+1];
  138. /*
  139. * corner dimension array - contains only the height or y_pos.
  140. * ----------------------------
  141. * DIMS_TC | DIMS_LEFT | DIMS_RIGHT |
  142. * |------------|-------------|
  143. * DIMS_BC | DIMS_LEFT | DIMS_RIGHT |
  144. * ----------------------------
  145. */
  146. typedef _DtCvUnit CornerDims[DIMS_BC+1][DIMS_RIGHT+1];
  147. /*
  148. * flow dimension array
  149. * -------------|--------------
  150. * DIMS_LEFT | DIMS_WIDTH | DIMS_HEIGHT |
  151. * | | DIMS_YPOS |
  152. * |------------|-------------|
  153. * DIMS_RIGHT | DIMS_WIDTH | DIMS_HEIGHT |
  154. * | | DIMS_YPOS |
  155. * ----------------------------
  156. */
  157. typedef _DtCvUnit FlowDims[DIMS_RIGHT+1][DIMS_HEIGHT+1];
  158. /*
  159. * margin data - important for determining flowing
  160. */
  161. typedef struct _dataPoint {
  162. _DtCvUnit left;
  163. _DtCvUnit right;
  164. _DtCvUnit y_pos;
  165. _DtCvUnit x_units;
  166. struct _dataPoint *next_pt;
  167. } DataPoint;
  168. /*
  169. * count information
  170. */
  171. typedef struct _cntInfo {
  172. int beg_txt;
  173. int end_txt;
  174. int beg_ln;
  175. int end_ln;
  176. int my_lines;
  177. int beg_brk;
  178. int end_brk;
  179. } CntInfo;
  180. /*
  181. * group information
  182. */
  183. typedef struct _grpInfo {
  184. _DtCvUnit min_x;
  185. _DtCvUnit max_x;
  186. _DtCvUnit top_y;
  187. _DtCvUnit bot_y;
  188. CntInfo cnt;
  189. struct _grpInfo *next_info;
  190. } GrpInfo;
  191. /*
  192. * layout information per container
  193. */
  194. typedef struct _layFrmtInfo {
  195. _DtCvUnit height;
  196. _DtCvUnit width;
  197. CntInfo cnt;
  198. struct _layFrmtInfo *next_info;
  199. } LayFrmtInfo;
  200. /*
  201. * the layout information carried around
  202. */
  203. typedef struct _layoutInfo {
  204. _DtCvUnit max_width; /* the current max width */
  205. _DtCvUnit id_Ypos; /* the y coordinate of the id found. */
  206. _DtCvUnit left; /* the current left margin for the
  207. current active container (incl br)*/
  208. _DtCvUnit right; /* the current right margin for the
  209. current active container (incl br)*/
  210. _DtCvUnit first; /* the current first indent */
  211. _DtCvUnit lmargin; /* the current absolute left margin */
  212. _DtCvUnit rmargin; /* the current absolute right margin */
  213. _DtCvUnit divisor; /* the current margin divisor */
  214. _DtCvUnit string_end;
  215. _DtCvUnit sub_end;
  216. _DtCvUnit super_end;
  217. _DtCvValue id_found; /* indicates if the id has been found*/
  218. _DtCvValue super_script;
  219. _DtCvValue sub_script;
  220. _DtCvValue stat_flag;
  221. _DtCvValue margin_non_zero;
  222. _DtCvValue brdr_flag; /* within container with a border */
  223. _DtCvValue table_flag; /* within table */
  224. _DtCvFrmtOption txt_justify;
  225. unsigned int cur_start; /* offset into the current segment
  226. to process */
  227. _DtCvSegmentI *lst_rendered; /* indicates the last string/region */
  228. char *target_id; /* if non-null, the id to search for */
  229. DataPoint *data_pts;
  230. GrpInfo *grp_lst; /* list of groups */
  231. _DtCvLayoutInfo info;
  232. } LayoutInfo;
  233. /*
  234. * information for laying out cells in a table.
  235. */
  236. typedef struct {
  237. int col_spn;
  238. int row_spn;
  239. _DtCvUnit pos_x;
  240. LayFrmtInfo info;
  241. _DtCvSegmentI *cell_seg;
  242. } CellInfo;
  243. /*
  244. * column description information for a table.
  245. */
  246. typedef struct _columnSpec {
  247. _DtCvUnit min;
  248. _DtCvUnit max;
  249. _DtCvUnit actual;
  250. _DtCvValue hanger;
  251. _DtCvFrmtOption justify;
  252. } ColumnSpec;
  253. /*
  254. * row description information
  255. */
  256. typedef struct _rowSpec {
  257. int column;
  258. _DtCvUnit y_adj;
  259. _DtCvUnit height;
  260. _DtCvUnit lst_height;
  261. char *next_id;
  262. } RowSpec;
  263. /*****************************************************************************
  264. * Private Variables/Data
  265. *****************************************************************************/
  266. static const LayFrmtInfo DefLayFrmtInfo = { 0, 0, {-1, -1, -1, -1, 0}, NULL };
  267. static const GrpInfo DefGrpInfo = { 0, 0, 0, 0, {-1, -1, -1, -1, 0}};
  268. static const LayoutInfo DefInfo = {
  269. 0, /* _DtCvUnit max_width; */
  270. 0, /* _DtCvUnit id_Ypos; */
  271. 0, /* _DtCvUnit left; */
  272. 0, /* _DtCvUnit right; */
  273. 0, /* _DtCvUnit first; */
  274. 0, /* _DtCvUnit lmargin; */
  275. 0, /* _DtCvUnit rmargin; */
  276. 1, /* _DtCvUnit divisor; */
  277. 0, /* _DtCvUnit string_end; */
  278. 0, /* _DtCvUnit sub_end; */
  279. 0, /* _DtCvUnit super_end; */
  280. False, /* _DtCvValue id_found; */
  281. False, /* _DtCvValue super_script; */
  282. False, /* _DtCvValue sub_script; */
  283. False, /* _DtCvValue stat_flag; */
  284. False, /* _DtCvValue margin_non_zero; */
  285. False, /* _DtCvValue brdr_flag; */
  286. False, /* _DtCvValue table_flag; */
  287. _DtCvJUSTIFY_LEFT, /* _DtCvFrmtOption txt_justify; */
  288. 0, /* unsigned int cur_start; */
  289. NULL, /* _DtCvSegmentI *lst_rendered; */
  290. NULL, /* char *target_id; */
  291. NULL, /* DataPoint *data_pts; */
  292. NULL, /* GrpInfo *data_pts; */
  293. };
  294. static const DataPoint DefDataPt = { 0, 0, _CEFORMAT_ALL, 0, NULL};
  295. static const double HeadDivisor = 10000.0;
  296. static const char *PeriodStr = ".";
  297. static const char *DefWidth[2] = { "", NULL };
  298. static const _DtCvSegmentI BlankTableCell =
  299. {
  300. _DtCvCONTAINER, /* type */
  301. -1, /* link_idx */
  302. { /* container info */
  303. NULL, /* id */
  304. NULL, /* justify_char */
  305. _DtCvDYNAMIC, /* type */
  306. _DtCvBORDER_NONE, /* border */
  307. _DtCvJUSTIFY_LEFT, /* justify */
  308. _DtCvJUSTIFY_TOP, /* vjustify */
  309. _DtCvJUSTIFY_LEFT, /* orient */
  310. _DtCvJUSTIFY_TOP, /* vorient */
  311. _DtCvWRAP_NONE, /* flow */
  312. 0, /* percent */
  313. 0, /* leading */
  314. 0, /* fmargin */
  315. 0, /* lmargin */
  316. 0, /* rmargin */
  317. 0, /* tmargin */
  318. 0, /* bmargin */
  319. _DtCvBORDER_NONE, /* bdr_info */
  320. NULL /* seg_list */
  321. },
  322. NULL, /* next_seg */
  323. NULL, /* next_disp */
  324. NULL, /* client_use */
  325. NULL /* internal_use */
  326. };
  327. /*****************************************************************************
  328. * Private Function Declarations
  329. *****************************************************************************/
  330. static void AdjustForBorders(
  331. _DtCanvasStruct *canvas,
  332. LayoutInfo *layout,
  333. _DtCvFrmtOption brdr,
  334. _DtCvUnit line_width,
  335. _DtCvUnit *ret_bot,
  336. _DtCvUnit *ret_right);
  337. static void AdjustHeadPosition(
  338. _DtCanvasStruct *canvas,
  339. LayoutInfo *layout,
  340. _DtCvSegmentI *p_seg,
  341. TopDims *top_bot,
  342. SideDims *side,
  343. CornerDims *corner,
  344. FlowDims *flow,
  345. LayFrmtInfo *info,
  346. _DtCvUnit base_y,
  347. _DtCvUnit base_left,
  348. _DtCvUnit block_width,
  349. _DtCvUnit left_margin,
  350. _DtCvUnit right_margin);
  351. static void AdjustObjectPosition(
  352. _DtCanvasStruct *canvas,
  353. LayoutInfo *layout,
  354. _DtCvFrmtOption justify,
  355. int start_txt,
  356. int start_ln,
  357. int start_brk,
  358. int end_txt,
  359. int end_ln,
  360. int end_brk,
  361. int brdr_cnt,
  362. _DtCvUnit height_adj,
  363. _DtCvUnit x_adj,
  364. _DtCvUnit y_adj,
  365. _DtCvUnit internal_y);
  366. static void CheckSaveInfo (
  367. _DtCanvasStruct *canvas,
  368. LayoutInfo *layout,
  369. _DtCvSegmentI *new_seg,
  370. int start);
  371. static void DetermineFlowConstraints(
  372. LayoutInfo *layout,
  373. FlowDims flow_dims,
  374. _DtCvUnit left_margin,
  375. _DtCvUnit right_margin,
  376. _DtCvUnit start_y,
  377. DataPoint *left_pt,
  378. DataPoint *right_pt);
  379. static void DetermineHeadPositioning(
  380. TopDims *top_bot,
  381. SideDims *side,
  382. CornerDims *corner,
  383. FlowDims *flow,
  384. _DtCvUnit start_y,
  385. _DtCvUnit max_top,
  386. _DtCvUnit block_size,
  387. _DtCvUnit *ret_side_size);
  388. static void DetermineMaxDims(
  389. TopDims *top_bot,
  390. CornerDims *corner,
  391. _DtCvUnit left_margin,
  392. _DtCvUnit right_margin,
  393. _DtCvUnit *top_height,
  394. _DtCvUnit *bot_height,
  395. _DtCvUnit *max_width);
  396. static int DrawBorders(
  397. _DtCanvasStruct *canvas,
  398. LayoutInfo *layout,
  399. _DtCvFrmtOption brdr,
  400. _DtCvPointer data,
  401. _DtCvUnit line_width,
  402. _DtCvUnit top_y,
  403. _DtCvUnit bot_y,
  404. _DtCvUnit left_x,
  405. _DtCvUnit right_x);
  406. static void FormatCell(
  407. _DtCanvasStruct *canvas,
  408. LayoutInfo *layout,
  409. _DtCvSegmentI *cell_seg,
  410. _DtCvUnit span_width,
  411. _DtCvUnit min_height,
  412. DataPoint base_pt,
  413. int *ret_ln,
  414. _DtCvUnit *ret_width,
  415. _DtCvUnit *ret_height,
  416. _DtCvValue *ret_tab_flag);
  417. static void InitDimArrays(
  418. TopDims *top_bot,
  419. SideDims *side,
  420. CornerDims *corner,
  421. FlowDims *flow);
  422. static _DtCvStatus LayoutCanvasInfo (
  423. _DtCanvasStruct *canvas,
  424. LayoutInfo *layout,
  425. _DtCvUnit divisor,
  426. char *target_id);
  427. static _DtCvValue LinesMayChange(
  428. _DtCanvasStruct *canvas,
  429. int start_ln,
  430. int end_ln,
  431. int brdr_cnt);
  432. static _DtCvUnit MoveGroup (
  433. _DtCanvasStruct *canvas,
  434. LayoutInfo *layout,
  435. GrpInfo *tst_grp,
  436. _DtCvUnit needed);
  437. static _DtCvUnit MoveLines (
  438. _DtCanvasStruct *canvas,
  439. LayoutInfo *layout,
  440. int idx,
  441. _DtCvUnit top_y,
  442. _DtCvUnit bot_y,
  443. _DtCvUnit needed);
  444. static _DtCvUnit MoveText (
  445. _DtCanvasStruct *canvas,
  446. LayoutInfo *layout,
  447. int idx,
  448. _DtCvUnit top_y,
  449. _DtCvUnit bot_y,
  450. _DtCvUnit needed);
  451. static void ProcessContainer(
  452. _DtCanvasStruct *canvas,
  453. LayoutInfo *layout,
  454. _DtCvSegmentI *con_seg,
  455. _DtCvUnit min_y,
  456. _DtCvUnit *ret_width,
  457. _DtCvUnit *ret_max_x,
  458. int *ret_cnt);
  459. static void ProcessSegmentList(
  460. _DtCanvasStruct *canvas,
  461. LayoutInfo *layout,
  462. _DtCvSegmentI *cur_seg,
  463. _DtCvUnit min_y,
  464. _DtCvUnit *ret_width,
  465. _DtCvUnit *ret_max_x,
  466. int **ret_vert);
  467. /******************************************************************************
  468. *
  469. * Private Functions
  470. *
  471. *****************************************************************************/
  472. /******************************************************************************
  473. * Function: AdjustTextPositions
  474. *
  475. * changes the baseline and text_x positioning of the text line by the
  476. * offsets indicated.
  477. *****************************************************************************/
  478. static void
  479. AdjustTextPositions(
  480. _DtCanvasStruct *canvas,
  481. int beg,
  482. int end,
  483. _DtCvUnit x_offset,
  484. _DtCvUnit y_offset)
  485. {
  486. if ( 0 != y_offset || 0 != x_offset)
  487. {
  488. while (beg < end)
  489. {
  490. canvas->txt_lst[beg].baseline += y_offset;
  491. canvas->txt_lst[beg].text_x += x_offset;
  492. beg++;
  493. }
  494. }
  495. }
  496. /******************************************************************************
  497. * Function: AdjustLinePositions
  498. *
  499. * changes the x & positions and the max x & y values by the offsets indicated.
  500. *****************************************************************************/
  501. static void
  502. AdjustLinePositions(
  503. _DtCanvasStruct *canvas,
  504. int beg,
  505. int end,
  506. _DtCvUnit x_offset,
  507. _DtCvUnit y_offset)
  508. {
  509. if ( 0 != y_offset || 0 != x_offset)
  510. {
  511. while (beg < end)
  512. {
  513. canvas->line_lst[beg].pos_y += y_offset;
  514. canvas->line_lst[beg].max_y += y_offset;
  515. canvas->line_lst[beg].pos_x += x_offset;
  516. canvas->line_lst[beg].max_x += x_offset;
  517. beg++;
  518. }
  519. }
  520. }
  521. /******************************************************************************
  522. * Function: AdjustPgBrk
  523. *
  524. * changes the y position of a page break.
  525. *****************************************************************************/
  526. static void
  527. AdjustPgBrk(
  528. _DtCanvasStruct *canvas,
  529. int beg,
  530. int end,
  531. _DtCvUnit y_offset)
  532. {
  533. if (0 != y_offset)
  534. {
  535. while (beg < end)
  536. canvas->pg_breaks[beg++] += y_offset;
  537. }
  538. }
  539. /******************************************************************************
  540. * Function: MaxXOfLine
  541. *
  542. * MaxXOfLine determines the max X of a line segment.
  543. *
  544. *****************************************************************************/
  545. /******************************************************************************
  546. * Function: MaxXOfLine
  547. *
  548. * MaxXOfLine determines the max X of a line segment.
  549. *
  550. *****************************************************************************/
  551. static _DtCvUnit
  552. MaxXOfLine(
  553. _DtCanvasStruct *canvas,
  554. _DtCvDspLine *line)
  555. {
  556. _DtCvValue lastLinkVisible = FALSE;
  557. int count = line->length;
  558. int start = line->byte_index;
  559. int len;
  560. int lnkInd = -1;
  561. _DtCvUnit xPos;
  562. _DtCvUnit tmpWidth;
  563. _DtCvSegmentI *pSeg;
  564. xPos = _DtCvGetStartXOfLine(line, &pSeg);
  565. while (pSeg != NULL && count > 0)
  566. {
  567. xPos = _DtCvAdvanceXOfLine(canvas, pSeg, xPos,
  568. &lnkInd, &lastLinkVisible);
  569. _DtCvGetWidthOfSegment(canvas, pSeg, start, count,
  570. &len, &tmpWidth, NULL);
  571. xPos += tmpWidth;
  572. count -= len;
  573. start = 0;
  574. pSeg = pSeg->next_disp;
  575. }
  576. return xPos;
  577. } /* End MaxXOfLine */
  578. /*****************************************************************************
  579. * Function: void GetLinkInfo ()
  580. *
  581. * Parameters:
  582. * canvas Specifies the handle for the canvas.
  583. *
  584. * Returns: A handle to the canvas or NULL if an error occurs.
  585. *
  586. * Purpose:
  587. *
  588. *****************************************************************************/
  589. static _DtCvValue
  590. GetLinkInfo (
  591. _DtCvHandle canvas_handle,
  592. int indx,
  593. _DtCvUnit *ret_x,
  594. _DtCvUnit *ret_y,
  595. _DtCvUnit *ret_width,
  596. _DtCvUnit *ret_height)
  597. {
  598. int len;
  599. int line;
  600. int count;
  601. int startChar;
  602. int lnkIndx = -1;
  603. _DtCvUnit startX;
  604. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  605. _DtCvSegmentI *pSeg;
  606. _DtCvValue lstVisible = False;
  607. _DtCvValue found = False;
  608. _DtCvValue junk;
  609. _DtCvUnit endX;
  610. void *pChar;
  611. /*
  612. * get the line index
  613. */
  614. line = canvas->trav_lst[indx].idx;
  615. /*
  616. * get some information from the line
  617. */
  618. pSeg = canvas->txt_lst[line].seg_ptr;
  619. count = canvas->txt_lst[line].length;
  620. startChar = canvas->txt_lst[line].byte_index;
  621. startX = canvas->txt_lst[line].text_x;
  622. *ret_y = canvas->txt_lst[line].baseline - canvas->txt_lst[line].ascent;
  623. *ret_height = canvas->txt_lst[line].ascent + canvas->txt_lst[line].descent;
  624. while (count > 0 && !found && pSeg != NULL)
  625. {
  626. if (startX < canvas->txt_lst[line].text_x)
  627. startX = canvas->txt_lst[line].text_x;
  628. /*
  629. * adjust the starting position by the link space
  630. */
  631. junk = _DtCvIsSegVisibleLink(pSeg);
  632. lstVisible = _DtCvModifyXpos (canvas->link_info, pSeg, junk,
  633. lstVisible, lnkIndx, &startX);
  634. /*
  635. * adjust the starting position by the traversal space
  636. */
  637. junk = _DtCvIsSegALink(pSeg);
  638. (void) _DtCvModifyXpos (canvas->traversal_info, pSeg, junk,
  639. ((_DtCvValue) True), lnkIndx, &startX);
  640. lnkIndx = pSeg->link_idx;
  641. /*
  642. * skip no-op
  643. */
  644. if (_DtCvIsSegNoop(pSeg))
  645. len = 0;
  646. /*
  647. * check region
  648. */
  649. else if (_DtCvIsSegRegion(pSeg))
  650. {
  651. len = 1;
  652. endX = startX + _DtCvWidthOfRegionSeg(pSeg);
  653. }
  654. else
  655. {
  656. /*
  657. * initialize the pointer to the string
  658. */
  659. pChar = _DtCvStrPtr(_DtCvStringOfStringSeg(pSeg),
  660. _DtCvIsSegWideChar(pSeg), startChar);
  661. /*
  662. * get the length of the current string.
  663. * If it is longer than the line count indicates,
  664. * it must be wrapped to the next line. We are
  665. * only interested in in the part of the line
  666. * that is on the line selected.
  667. */
  668. len = _DtCvStrLen (pChar, _DtCvIsSegWideChar(pSeg));
  669. if (len > count)
  670. len = count;
  671. /*
  672. * calculate the ending pixel postion for
  673. * this string segment.
  674. */
  675. endX = startX + _DtCvGetStringWidth(canvas,pSeg,pChar,len);
  676. }
  677. /*
  678. * test to see if the selected segment was this segment.
  679. */
  680. if (pSeg == canvas->trav_lst[indx].seg_ptr)
  681. {
  682. found = True;
  683. *ret_x = startX;
  684. *ret_width = endX - startX;
  685. }
  686. else
  687. {
  688. /*
  689. * go to the next segment.
  690. */
  691. pSeg = pSeg->next_disp;
  692. /*
  693. * adjust for the new begining.
  694. */
  695. startX = endX;
  696. count = count - len;
  697. startChar = 0;
  698. }
  699. }
  700. return found;
  701. }
  702. /******************************************************************************
  703. * Function: CheckId
  704. *
  705. * Check to see if the id matches the target id.
  706. * If so, set the 'found id' flag and indicate its y coordinate.
  707. *****************************************************************************/
  708. static void
  709. CheckId(
  710. LayoutInfo *layout,
  711. char *id)
  712. {
  713. if (layout->target_id != NULL && NULL != id &&
  714. _DtCvStrCaseCmpLatin1(id, layout->target_id) == 0)
  715. {
  716. layout->id_Ypos = layout->info.y_pos;
  717. layout->id_found = True;
  718. }
  719. }
  720. /******************************************************************************
  721. * Function: CheckSetLineStart
  722. *
  723. * Check to see if the line information is at the beginning.
  724. * If so, set the pointers to the current segment and offset.
  725. *****************************************************************************/
  726. static void
  727. CheckSetLineStart(
  728. LayoutInfo *layout,
  729. _DtCvSegmentI *cur_seg)
  730. {
  731. if (layout->info.line_bytes == 0)
  732. {
  733. layout->info.line_seg = cur_seg;
  734. layout->info.line_start = 0;
  735. }
  736. }
  737. /******************************************************************************
  738. * Function: CheckForPageBreak
  739. *
  740. * Check to see if there is a page break on this segment.
  741. * If so, remember its position.
  742. *****************************************************************************/
  743. static int
  744. CheckForPageBreak(
  745. _DtCanvasStruct *canvas,
  746. _DtCvSegmentI *cur_seg,
  747. _DtCvUnit position)
  748. {
  749. /*
  750. * does this segment cause a page break?
  751. */
  752. if (_DtCvIsSegPageBreak(cur_seg))
  753. {
  754. /*
  755. * check to see if there is room to save the page break.
  756. * if not, allocate more room.
  757. */
  758. if (canvas->brk_cnt >= canvas->brk_max)
  759. {
  760. canvas->brk_max += GROW_SIZE;
  761. if (NULL != canvas->pg_breaks)
  762. canvas->pg_breaks = (_DtCvUnit *) realloc (
  763. (void *) canvas->pg_breaks,
  764. (sizeof(_DtCvUnit) * canvas->brk_max));
  765. else
  766. canvas->pg_breaks = (_DtCvUnit *) malloc (
  767. (sizeof(_DtCvUnit) * canvas->brk_max));
  768. }
  769. /*
  770. * failed to allocate memory, abort.
  771. */
  772. if (NULL == canvas->pg_breaks)
  773. {
  774. canvas->brk_max = 0;
  775. canvas->brk_cnt = 0;
  776. return 1;
  777. }
  778. /*
  779. * save the y position of the page break for later.
  780. */
  781. canvas->pg_breaks[canvas->brk_cnt++] = position;
  782. }
  783. return 0;
  784. }
  785. /******************************************************************************
  786. * Function: SetBeginCounts
  787. *
  788. * Parameters:
  789. * canvas Specifies the canvas.
  790. * f_info Specifies the layout count info.
  791. *
  792. * Returns: Nothing
  793. *
  794. * Purpose: Initializes the layout count information for a container.
  795. *****************************************************************************/
  796. static void
  797. SetBeginCounts (
  798. _DtCanvasStruct *canvas,
  799. CntInfo *cnt_info)
  800. {
  801. /*
  802. * text counts
  803. */
  804. cnt_info->beg_txt = canvas->txt_cnt;
  805. cnt_info->end_txt = canvas->txt_cnt;
  806. /*
  807. * line counts
  808. */
  809. cnt_info->beg_ln = canvas->line_cnt;
  810. cnt_info->end_ln = canvas->line_cnt;
  811. /*
  812. * break counts
  813. */
  814. cnt_info->beg_brk = canvas->brk_cnt;
  815. cnt_info->end_brk = canvas->brk_cnt;
  816. }
  817. /******************************************************************************
  818. * Function: SetEndCounts
  819. *
  820. * Parameters:
  821. * canvas Specifies the canvas.
  822. * f_info Specifies the layout count info.
  823. *
  824. * Returns: Nothing
  825. *
  826. * Purpose: Sets the ending layout counts for a container.
  827. *****************************************************************************/
  828. static void
  829. SetEndCounts (
  830. _DtCanvasStruct *canvas,
  831. CntInfo *cnt_info,
  832. int end_ln)
  833. {
  834. /*
  835. * text counts
  836. */
  837. cnt_info->end_txt = canvas->txt_cnt;
  838. /*
  839. * line counts
  840. */
  841. cnt_info->end_ln = canvas->line_cnt;
  842. /*
  843. * break counts
  844. */
  845. cnt_info->end_brk = canvas->brk_cnt;
  846. /*
  847. * the number of lines for this container.
  848. * If negative, indicates the first line is for the
  849. * bottom of the container and goes the length.
  850. */
  851. cnt_info->my_lines = end_ln;
  852. }
  853. /******************************************************************************
  854. * Function: SkipToNumber
  855. *
  856. * Returns:
  857. *****************************************************************************/
  858. static void
  859. SkipToNumber (
  860. const char **string)
  861. {
  862. if (string != NULL)
  863. {
  864. const char *str = *string;
  865. while (*str == ' ' && *str != '\0')
  866. str++;
  867. *string = str;
  868. }
  869. }
  870. /******************************************************************************
  871. * Function: GetValueFromString
  872. *
  873. * Returns:
  874. *****************************************************************************/
  875. static int
  876. GetValueFromString (
  877. const char **string,
  878. int def_num)
  879. {
  880. int value = def_num;
  881. if (string != NULL && *string != NULL && **string != '\0')
  882. {
  883. const char *str = *string;
  884. if ('0' <= *str && *str <= '9')
  885. value = atoi(str);
  886. while ('0' <= *str && *str <= '9')
  887. str++;
  888. while (*str != ' ' && *str != '\0' && (*str < '0' || *str > '9'))
  889. str++;
  890. *string = str;
  891. }
  892. return value;
  893. }
  894. /******************************************************************************
  895. * Function: PushDataPoint
  896. *
  897. * Returns:
  898. *****************************************************************************/
  899. static void
  900. PushDataPoint (
  901. LayoutInfo *layout,
  902. DataPoint *data_pt)
  903. {
  904. data_pt->x_units = 0;
  905. data_pt->next_pt = layout->data_pts;
  906. layout->data_pts = data_pt;
  907. }
  908. /******************************************************************************
  909. * Function: InsertDataPoint
  910. *
  911. * Returns:
  912. *****************************************************************************/
  913. static void
  914. InsertDataPoint (
  915. LayoutInfo *layout,
  916. DataPoint *data_pt)
  917. {
  918. DataPoint *lastPt = NULL;
  919. DataPoint *nextPt = layout->data_pts;
  920. while (nextPt != NULL &&
  921. nextPt->y_pos != _CEFORMAT_ALL &&
  922. (data_pt->y_pos == _CEFORMAT_ALL || nextPt->y_pos < data_pt->y_pos))
  923. {
  924. lastPt = nextPt;
  925. nextPt = nextPt->next_pt;
  926. }
  927. data_pt->next_pt = nextPt;
  928. data_pt->x_units = 0;
  929. if (lastPt == NULL)
  930. layout->data_pts = data_pt;
  931. else
  932. lastPt->next_pt = data_pt;
  933. }
  934. /******************************************************************************
  935. * Function: RemoveDataPoint
  936. *
  937. * Returns:
  938. *****************************************************************************/
  939. static void
  940. RemoveDataPoint (
  941. LayoutInfo *layout,
  942. DataPoint *data_pt)
  943. {
  944. DataPoint *lastPt = NULL;
  945. DataPoint *curPt = layout->data_pts;
  946. while (curPt != NULL && curPt != data_pt)
  947. {
  948. lastPt = curPt;
  949. curPt = curPt->next_pt;
  950. }
  951. if (curPt != NULL)
  952. {
  953. data_pt->x_units = layout->info.cur_max_x - data_pt->left;
  954. if (lastPt == NULL)
  955. layout->data_pts = curPt->next_pt;
  956. else
  957. lastPt->next_pt = curPt->next_pt;
  958. }
  959. }
  960. /******************************************************************************
  961. * Function: GetCurrentDataPoint
  962. *
  963. * Returns:
  964. *****************************************************************************/
  965. static void
  966. GetCurrentDataPoint (
  967. LayoutInfo *layout,
  968. DataPoint *data_pt)
  969. {
  970. data_pt->left = 0;
  971. data_pt->right = 0;
  972. data_pt->y_pos = _CEFORMAT_ALL;
  973. if (layout->data_pts != NULL)
  974. *data_pt = *(layout->data_pts);
  975. }
  976. /******************************************************************************
  977. * Function: SetMargins
  978. *
  979. * Purpose: Sets the margins.
  980. *****************************************************************************/
  981. static void
  982. SetMargins (
  983. LayoutInfo *layout)
  984. {
  985. layout->lmargin = 0;
  986. layout->rmargin = 0;
  987. layout->info.format_y = _CEFORMAT_ALL;
  988. if (layout->data_pts != NULL)
  989. {
  990. /*
  991. * base
  992. */
  993. layout->lmargin = layout->data_pts->left;
  994. layout->rmargin = layout->data_pts->right;
  995. layout->info.format_y = layout->data_pts->y_pos;
  996. }
  997. layout->lmargin += layout->left;
  998. layout->rmargin += layout->right;
  999. }
  1000. /******************************************************************************
  1001. * Function: SetTextPosition
  1002. *
  1003. * Purpose: Sets the text beginning position to the left margin.
  1004. * If 'first' is true, adds its value to the text beginning
  1005. * position value.
  1006. *****************************************************************************/
  1007. static void
  1008. SetTextPosition (
  1009. LayoutInfo *layout,
  1010. _DtCvValue first)
  1011. {
  1012. layout->info.text_x_pos = layout->lmargin;
  1013. if (first == True)
  1014. layout->info.text_x_pos += layout->first;
  1015. }
  1016. /******************************************************************************
  1017. * Function: CheckFormat
  1018. *
  1019. * Purpose: Checks to see if the flowing txt boundaries have been exceeded.
  1020. * If a boundary has been exceeded, then removes that boundary
  1021. * information from the stack until it finds a valid boundary point.
  1022. *
  1023. * Calls SetMargins to set the correct margin
  1024. * Calls SetTextPosition to set the text beginning position.
  1025. *****************************************************************************/
  1026. static void
  1027. CheckFormat (
  1028. LayoutInfo *layout,
  1029. _DtCvValue first)
  1030. {
  1031. while (layout->data_pts != NULL &&
  1032. layout->data_pts->y_pos != _CEFORMAT_ALL &&
  1033. layout->data_pts->y_pos < layout->info.y_pos)
  1034. RemoveDataPoint (layout, layout->data_pts);
  1035. SetMargins(layout);
  1036. SetTextPosition(layout, first);
  1037. }
  1038. /******************************************************************************
  1039. * Function: SaveLine
  1040. *
  1041. * Initializes a line table element to the segment it should display.
  1042. *****************************************************************************/
  1043. static void
  1044. SaveLine (
  1045. _DtCanvasStruct *canvas,
  1046. LayoutInfo *layout,
  1047. int direction,
  1048. _DtCvPointer data,
  1049. _DtCvUnit line_width,
  1050. _DtCvUnit x,
  1051. _DtCvUnit y,
  1052. _DtCvUnit length)
  1053. {
  1054. int i = canvas->line_cnt;
  1055. _DtCvUnit x2 = x;
  1056. _DtCvUnit y2 = y;
  1057. if (i >= canvas->line_max)
  1058. {
  1059. canvas->line_max += GROW_SIZE;
  1060. if (canvas->line_lst)
  1061. canvas->line_lst = (_DtCvLineSeg *) realloc (
  1062. (void *) canvas->line_lst,
  1063. (sizeof(_DtCvLineSeg) * canvas->line_max));
  1064. else
  1065. canvas->line_lst = (_DtCvLineSeg *) malloc (
  1066. (sizeof(_DtCvLineSeg) * canvas->line_max));
  1067. /*
  1068. * NOTE....should this routine return a value?
  1069. * If (re)alloc error occurs, this simply ignores the problem.
  1070. */
  1071. if (canvas->line_lst == NULL)
  1072. {
  1073. canvas->line_max = 0;
  1074. canvas->line_cnt = 0;
  1075. return;
  1076. }
  1077. }
  1078. /*
  1079. * does this line exceed the current maximum?
  1080. */
  1081. if (_DtCvLINE_HORZ == direction)
  1082. {
  1083. x2 += length;
  1084. y2 += line_width;
  1085. }
  1086. else
  1087. {
  1088. x2 += line_width;
  1089. y2 += length;
  1090. }
  1091. if (layout->info.max_x_pos < x2)
  1092. layout->info.max_x_pos = x2;
  1093. if (layout->info.cur_max_x < x2)
  1094. layout->info.cur_max_x = x2;
  1095. /*
  1096. * save the line information
  1097. */
  1098. canvas->line_lst[i].dir = direction;
  1099. canvas->line_lst[i].pos_x = x;
  1100. canvas->line_lst[i].max_x = x2;
  1101. canvas->line_lst[i].pos_y = y;
  1102. canvas->line_lst[i].max_y = y2;
  1103. canvas->line_lst[i].width = line_width;
  1104. canvas->line_lst[i].data = data;
  1105. canvas->line_cnt++;
  1106. }
  1107. /******************************************************************************
  1108. * Function: SaveInfo
  1109. *
  1110. * Purpose: Saves the current information into the txt line struct.
  1111. * Checks to see if this line exceeds the flowing text
  1112. * boundary and resets the internal global margins.
  1113. *****************************************************************************/
  1114. static void
  1115. SaveInfo (
  1116. _DtCanvasStruct *canvas,
  1117. LayoutInfo *layout,
  1118. _DtCvSegmentI *new_seg,
  1119. int start)
  1120. {
  1121. _DtCvSaveInfo (canvas, &(layout->info),
  1122. layout->max_width, layout->rmargin, layout->txt_justify);
  1123. while (layout->info.delayed_search_saves > 0) {
  1124. _DtCvSetSearchEntryInfo(canvas, canvas->txt_cnt - 1);
  1125. layout->info.delayed_search_saves--;
  1126. }
  1127. layout->super_end = 0;
  1128. layout->sub_end = 0;
  1129. layout->super_script = False;
  1130. layout->sub_script = False;
  1131. layout->info.line_seg = new_seg;
  1132. layout->info.line_start = start;
  1133. layout->info.cur_len = 0;
  1134. CheckFormat(layout, FALSE);
  1135. }
  1136. /******************************************************************************
  1137. * Function: CheckSaveInfo
  1138. *
  1139. * Purpose: Checks to see if there is any information to save and saves
  1140. * it if there is any.
  1141. *****************************************************************************/
  1142. static void
  1143. CheckSaveInfo (
  1144. _DtCanvasStruct *canvas,
  1145. LayoutInfo *layout,
  1146. _DtCvSegmentI *new_seg,
  1147. int start)
  1148. {
  1149. if (layout->info.line_bytes)
  1150. SaveInfo (canvas, layout, new_seg, start);
  1151. }
  1152. /******************************************************************************
  1153. * Function: ProcessStringSegment
  1154. *
  1155. * chops a string segment up until its completely used.
  1156. *
  1157. *****************************************************************************/
  1158. static void
  1159. ProcessStringSegment(
  1160. _DtCanvasStruct *canvas,
  1161. LayoutInfo *layout,
  1162. _DtCvSegmentI *cur_seg)
  1163. {
  1164. layout->cur_start = 0;
  1165. if (!(_DtCvIsSegSuperScript(cur_seg) || _DtCvIsSegSubScript(cur_seg))
  1166. && (layout->super_script == True || layout->sub_script == True))
  1167. {
  1168. layout->super_end = 0;
  1169. layout->sub_end = 0;
  1170. layout->super_script = False;
  1171. layout->sub_script = False;
  1172. }
  1173. while (_DtCvProcessStringSegment(canvas, &(layout->info),
  1174. layout->max_width, layout->lmargin, layout->rmargin,
  1175. cur_seg , &(layout->cur_start),
  1176. layout->txt_justify, layout->stat_flag) == 1)
  1177. CheckFormat(layout, False);
  1178. } /* End ProcessStringSegment */
  1179. /******************************************************************************
  1180. * Function: _DtCvUnit ResolveHeight(
  1181. *
  1182. * Parameters:
  1183. *
  1184. * Purpose: Determines the height of a row that is spanned.
  1185. *****************************************************************************/
  1186. static _DtCvUnit
  1187. ResolveHeight(
  1188. RowSpec *row_info,
  1189. CellInfo *cell_info,
  1190. int max_cols,
  1191. int row,
  1192. int span)
  1193. {
  1194. int i;
  1195. int col;
  1196. int cell;
  1197. int topRow;
  1198. int topCell;
  1199. int zeroed;
  1200. int total;
  1201. int rowHeight = 0;
  1202. for (col = 0, cell = row * max_cols; col < max_cols; col++, cell++)
  1203. {
  1204. /*
  1205. * if we have a row spanning cell in this column,
  1206. * but it isn't from a previous column, try to fill out
  1207. * the height using it.
  1208. */
  1209. if (cell_info[cell].row_spn == -1 && cell_info[cell].col_spn != -1)
  1210. {
  1211. /*
  1212. * back up to the cell information containing the row
  1213. * span value.
  1214. */
  1215. topRow = row;
  1216. topCell = cell;
  1217. do
  1218. {
  1219. topCell--;
  1220. topRow--;
  1221. } while (cell_info[topCell].row_spn == -1);
  1222. /*
  1223. * from here, start calculating the height of the row
  1224. * spanning cell, and find out how big the row must
  1225. * be to contain it.
  1226. */
  1227. i = cell_info[topCell].row_spn;
  1228. zeroed = span + 1;
  1229. total = 0;
  1230. while (i > 0 && zeroed > 0)
  1231. {
  1232. total += row_info[topRow].height;
  1233. if (row_info[topRow].height == 0)
  1234. zeroed--;
  1235. i--;
  1236. topRow++;
  1237. }
  1238. /*
  1239. * if zeroed is greater than zero, that means only the
  1240. * allowd number of row heights were zeroed out (the ones
  1241. * we are looking for).
  1242. * go ahead and calculate a new height. Otherwise,
  1243. * it may be tried later.
  1244. */
  1245. if (zeroed > 0)
  1246. {
  1247. /*
  1248. * make sure we get a positive value out of
  1249. * this for our height.
  1250. */
  1251. if (cell_info[topCell].info.height > total)
  1252. {
  1253. total = cell_info[topCell].info.height - total;
  1254. total = total / span + (total % span ? 1 : 0);
  1255. }
  1256. /*
  1257. * make sure we take the biggest value possible
  1258. * for this row. If it needs to be smaller for
  1259. * cells, we'll adjust the positioning within
  1260. * the cell.
  1261. */
  1262. if (rowHeight < total)
  1263. rowHeight = total;
  1264. }
  1265. }
  1266. }
  1267. row_info[row].height = rowHeight;
  1268. return rowHeight;
  1269. }
  1270. /******************************************************************************
  1271. * Function: void AdjustHeight(
  1272. *
  1273. * Parameters:
  1274. *
  1275. * Purpose: Determines the height of rows that are spanned but the
  1276. * the spanner needs more room than the calculated row height
  1277. * allow.
  1278. *****************************************************************************/
  1279. static void
  1280. AdjustHeight(
  1281. CellInfo *cell_info,
  1282. RowSpec *row_specs,
  1283. int max_cols,
  1284. int row,
  1285. int col)
  1286. {
  1287. int cell = row * max_cols + col;
  1288. int i, j;
  1289. _DtCvUnit total;
  1290. _DtCvUnit adjustValue;
  1291. _DtCvUnit value;
  1292. if (cell_info[cell].col_spn == -1 || cell_info[cell].row_spn == -1)
  1293. return;
  1294. for (j = row, i = 0, total = 0; i < cell_info[cell].row_spn; i++, j++)
  1295. total += row_specs[j].height;
  1296. /*
  1297. * adjust the row height to include all of the row spanning cell.
  1298. */
  1299. if (total < cell_info[cell].info.height)
  1300. {
  1301. _DtCvUnit totalUsed = 0;
  1302. /*
  1303. * first, try to grow the cells on a percentage basis.
  1304. * This way, a small cell will grow the same amount relative
  1305. * to the larger cells.
  1306. */
  1307. adjustValue = cell_info[cell].info.height - total;
  1308. /*
  1309. * now if total is zero, we'll get a divide by zero error.
  1310. * So check for this and set total to the number of rows spanned.
  1311. */
  1312. if (0 == total)
  1313. total = cell_info[cell].row_spn;
  1314. for (i = 0; i < cell_info[cell].row_spn; i++)
  1315. {
  1316. value = (((row_specs[row + i].height * 100) / total) * adjustValue)
  1317. / 100;
  1318. row_specs[row + i].height += value;
  1319. totalUsed += value;
  1320. }
  1321. /*
  1322. * if didn't use all the size up - apply it evenly.
  1323. */
  1324. if (totalUsed < adjustValue)
  1325. {
  1326. adjustValue = adjustValue - totalUsed;
  1327. for (i = 0, j = cell_info[cell].row_spn;
  1328. adjustValue > 0 && i < cell_info[cell].row_spn; i++, j--)
  1329. {
  1330. value = adjustValue / j + (adjustValue % j ? 1 : 0);
  1331. row_specs[row + i].height += value;
  1332. adjustValue -= value;
  1333. totalUsed += value;
  1334. }
  1335. }
  1336. total = totalUsed;
  1337. }
  1338. }
  1339. /******************************************************************************
  1340. * Function: void ReFormatCell(
  1341. *
  1342. * Parameters:
  1343. * canvas Specifies the specific information about the
  1344. * rendering area.
  1345. * layout Specifies the currently active information
  1346. * affecting the layout of information.
  1347. *
  1348. * Purpose: Based on a height and width, relay out the information in a cell.
  1349. *****************************************************************************/
  1350. static void
  1351. ReFormatCell(
  1352. _DtCanvasStruct *canvas,
  1353. LayoutInfo *layout,
  1354. CellInfo *this_cell,
  1355. ColumnSpec *col_specs,
  1356. int col,
  1357. _DtCvUnit new_height,
  1358. _DtCvUnit new_y)
  1359. {
  1360. int i;
  1361. int saveTxt = canvas->txt_cnt;
  1362. int saveLn = canvas->line_cnt;
  1363. _DtCvUnit saveYpos = layout->info.y_pos;
  1364. _DtCvUnit saveMaxX = layout->info.cur_max_x;
  1365. _DtCvUnit cellWidth = 0;
  1366. _DtCvUnit junk;
  1367. _DtCvValue junkValue;
  1368. DataPoint basePt;
  1369. /*
  1370. * reset the y_pos to the correct placement.
  1371. * reset the line counts to the original values.
  1372. * since we aren't changing the width, the number
  1373. * of lines used will not change.
  1374. */
  1375. layout->info.y_pos = new_y;
  1376. canvas->txt_cnt = this_cell->info.cnt.beg_txt;
  1377. canvas->line_cnt = this_cell->info.cnt.beg_ln;
  1378. /*
  1379. * determine the maximum width for the cell.
  1380. */
  1381. for (i = this_cell->col_spn; i > 0; i--)
  1382. cellWidth += col_specs[col++].actual;
  1383. /*
  1384. * get the current left and right margins.
  1385. */
  1386. GetCurrentDataPoint(layout, &basePt);
  1387. /*
  1388. * re-format the cell
  1389. */
  1390. FormatCell(canvas, layout, this_cell->cell_seg, cellWidth,
  1391. new_height,
  1392. basePt, &i, &cellWidth, &junk, &junkValue);
  1393. /*
  1394. * calculate the new height.
  1395. */
  1396. this_cell->info.height = layout->info.y_pos - new_y;
  1397. /*
  1398. * if the new cell does not use the same number of lines as the
  1399. * old formatting did, zero the length.
  1400. */
  1401. while (canvas->txt_cnt < this_cell->info.cnt.end_txt)
  1402. canvas->txt_lst[canvas->txt_cnt++].length = 0;
  1403. /*
  1404. * restore the saved counters
  1405. */
  1406. canvas->txt_cnt = saveTxt;
  1407. canvas->line_cnt = saveLn;
  1408. layout->info.y_pos = saveYpos;
  1409. layout->info.cur_max_x = saveMaxX;
  1410. }
  1411. /******************************************************************************
  1412. * Function: void FormatCell(
  1413. *
  1414. * Parameters:
  1415. * canvas Specifies the specific information about the
  1416. * rendering area.
  1417. * layout Specifies the currently active information
  1418. * affecting the layout of information.
  1419. * span_width Specifies the desired size constraining
  1420. * the layout of information.
  1421. * base_pt Specifies the base margins.
  1422. * this_cell Specifies the cell structure to fill out.
  1423. *
  1424. * Purpose: Determines the width and height of the cell. Also the begin/end
  1425. * counts on text, graphics and lines.
  1426. *****************************************************************************/
  1427. static void
  1428. FormatCell(
  1429. _DtCanvasStruct *canvas,
  1430. LayoutInfo *layout,
  1431. _DtCvSegmentI *cell_seg,
  1432. _DtCvUnit span_width,
  1433. _DtCvUnit min_height,
  1434. DataPoint base_pt,
  1435. int *ret_ln,
  1436. _DtCvUnit *ret_width,
  1437. _DtCvUnit *ret_height,
  1438. _DtCvValue *ret_tab_flag)
  1439. {
  1440. _DtCvStatus only1Col = True;
  1441. _DtCvUnit maxX;
  1442. _DtCvUnit minY = -1;
  1443. _DtCvUnit saveYpos = layout->info.y_pos;
  1444. _DtCvUnit saveRight = layout->right;
  1445. _DtCvUnit saveMaxX = layout->info.cur_max_x;
  1446. _DtCvSegmentI *nextSeg;
  1447. /*
  1448. * set the limits/margins
  1449. * assume the left_margin has been set by a previous call.
  1450. */
  1451. layout->right = layout->max_width - base_pt.left - base_pt.right
  1452. - layout->left - span_width;
  1453. /*
  1454. * set the minimum Y for the container.
  1455. */
  1456. if (0 < min_height)
  1457. minY = saveYpos + min_height;
  1458. /*
  1459. * If a segment was specified for this cell, format it.
  1460. */
  1461. if (cell_seg != NULL && &BlankTableCell != cell_seg)
  1462. {
  1463. ProcessContainer(canvas, layout, cell_seg, minY,
  1464. ret_width, &maxX, ret_ln);
  1465. /*
  1466. * check to see if the only thing in this container is a
  1467. * table.
  1468. */
  1469. nextSeg = _DtCvContainerListOfSeg(cell_seg);
  1470. *ret_tab_flag = True;
  1471. while (True == *ret_tab_flag && NULL != nextSeg)
  1472. {
  1473. /*
  1474. * check to see if there is any segments that aren't one
  1475. * column tables.
  1476. */
  1477. if (_DtCvIsSegTable(nextSeg) &&
  1478. 1 < _DtCvNumColsOfTableSeg(nextSeg))
  1479. only1Col = False;
  1480. else if (!(_DtCvIsSegTable(nextSeg) || _DtCvIsSegNoop(nextSeg)))
  1481. *ret_tab_flag = False;
  1482. nextSeg = _DtCvNextSeg(nextSeg);
  1483. }
  1484. if (True == *ret_tab_flag && True == only1Col)
  1485. *ret_tab_flag = False;
  1486. }
  1487. /*
  1488. * Calculate the height and return it.
  1489. */
  1490. *ret_height = layout->info.y_pos - saveYpos;
  1491. /*
  1492. * restore the right margin
  1493. */
  1494. layout->right = saveRight;
  1495. if (layout->info.cur_max_x < saveMaxX)
  1496. layout->info.cur_max_x = saveMaxX;
  1497. }
  1498. /******************************************************************************
  1499. * Function: AdjustFrmtTxtOption
  1500. *
  1501. *****************************************************************************/
  1502. static void
  1503. AdjustFrmtTxtOption(
  1504. _DtCvSegmentI *p_seg,
  1505. _DtCvFrmtOption option)
  1506. {
  1507. if (p_seg != NULL && _DtCvIsSegContainer(p_seg))
  1508. {
  1509. TxtHorizJustify(p_seg) = option;
  1510. p_seg = _DtCvContainerListOfSeg(p_seg);
  1511. while (p_seg != NULL)
  1512. {
  1513. AdjustFrmtTxtOption(p_seg, option);
  1514. p_seg = p_seg->next_seg;
  1515. }
  1516. }
  1517. }
  1518. /******************************************************************************
  1519. * Function: ResolveCell
  1520. *
  1521. *****************************************************************************/
  1522. static _DtCvValue
  1523. ResolveCell(
  1524. _DtCanvasStruct *canvas,
  1525. LayoutInfo *layout,
  1526. _DtCvSegmentI *table,
  1527. ColumnSpec *col_specs,
  1528. RowSpec *row_specs,
  1529. int col,
  1530. int row,
  1531. int max_cols,
  1532. int max_rows,
  1533. CellInfo *ret_info)
  1534. {
  1535. register int i;
  1536. char *id;
  1537. char *idRefs;
  1538. char *ptr;
  1539. char c;
  1540. int count;
  1541. int len;
  1542. int done;
  1543. int brdCnt;
  1544. int myCol = col;
  1545. int cell = row * max_cols + col;
  1546. _DtCvUnit cellWidth;
  1547. _DtCvUnit retWidth;
  1548. _DtCvUnit retHeight;
  1549. _DtCvUnit saveTop;
  1550. CellInfo *thisCell = &ret_info[cell];
  1551. DataPoint basePt;
  1552. _DtCvValue reformat = False;
  1553. _DtCvValue retTabFlag = False;
  1554. _DtCvSegmentI **f_data = _DtCvCellsOfTableSeg(table);
  1555. /*
  1556. * if this column is spanned, skip
  1557. */
  1558. if (thisCell->col_spn == -1 || thisCell->row_spn == -1)
  1559. return False;
  1560. GetCurrentDataPoint(layout, &basePt);
  1561. if (thisCell->cell_seg == NULL)
  1562. {
  1563. idRefs = row_specs[row].next_id;
  1564. /*
  1565. * find the end of the id
  1566. */
  1567. done = False;
  1568. /*
  1569. * set the starting info
  1570. */
  1571. thisCell->col_spn = 1;
  1572. thisCell->pos_x = basePt.left + layout->left;
  1573. while (!done && col < max_cols)
  1574. {
  1575. ptr = idRefs;
  1576. id = idRefs;
  1577. /*
  1578. * move the ptr to the next id,
  1579. * counting the characters in this id at the same time.
  1580. */
  1581. len = 0;
  1582. while (NULL != ptr && *ptr != ' ' && *ptr != '\0')
  1583. {
  1584. ptr++;
  1585. len++;
  1586. }
  1587. /*
  1588. * set idRefs to the next id.
  1589. */
  1590. idRefs = ptr;
  1591. while (NULL != idRefs && *idRefs == ' ')
  1592. idRefs++;
  1593. /*
  1594. * Is this id and the next the same? If so,
  1595. * it spans the columns
  1596. */
  1597. if (0 != len && _DtCvStrNCaseCmpLatin1(id, idRefs, len) == 0 &&
  1598. (idRefs[len] == ' ' || idRefs[len] == '\0'))
  1599. {
  1600. col++;
  1601. thisCell->col_spn++;
  1602. ret_info[++cell].col_spn = -1;
  1603. }
  1604. else
  1605. done = True;
  1606. }
  1607. row_specs[row].next_id = idRefs;
  1608. /*
  1609. * find the segment
  1610. */
  1611. if (NULL != id && '\0' != *id)
  1612. {
  1613. c = *ptr;
  1614. *ptr = '\0';
  1615. while (f_data != NULL && NULL != *f_data &&
  1616. _DtCvStrCaseCmpLatin1(_DtCvContainerIdOfSeg(*f_data),id) != 0)
  1617. f_data++;
  1618. /*
  1619. * make sure to break the link to the next segment.
  1620. * Otherwise, the formatting routines will format too much
  1621. * for the cell.
  1622. */
  1623. if (NULL != f_data && NULL != *f_data)
  1624. {
  1625. _DtCvNextSeg(*f_data) = NULL;
  1626. /*
  1627. * assign the data to this cell.
  1628. */
  1629. thisCell->cell_seg = *f_data;
  1630. }
  1631. else /* there is no id for this cell, use a blank container */
  1632. thisCell->cell_seg = (struct _dtCvSegment*) &BlankTableCell;
  1633. }
  1634. else /* there is no id for this cell, use a blank container */
  1635. thisCell->cell_seg = (struct _dtCvSegment*) &BlankTableCell;
  1636. /*
  1637. * how many rows does this cell span?
  1638. */
  1639. len = 0;
  1640. if (NULL != id)
  1641. len = strlen(id);
  1642. for (done = False, count = 1, i = row + 1;
  1643. 0 < len && i < max_rows && False == done; i++)
  1644. {
  1645. done = True;
  1646. if (_DtCvStrNCaseCmpLatin1(id, row_specs[i].next_id, len) == 0 &&
  1647. (row_specs[i].next_id[len] == ' ' ||
  1648. row_specs[i].next_id[len] == '\0'))
  1649. {
  1650. int k;
  1651. done = False;
  1652. count++;
  1653. /*
  1654. * invalidate the columns spanned in this row
  1655. */
  1656. for (k = 0; k < thisCell->col_spn && k + myCol < max_cols; k++)
  1657. {
  1658. ret_info[i * max_cols + myCol + k].col_spn = -1;
  1659. ret_info[i * max_cols + myCol + k].row_spn = -1;
  1660. }
  1661. idRefs = row_specs[i].next_id;
  1662. do
  1663. {
  1664. /*
  1665. * skip the current id.
  1666. */
  1667. while (*idRefs != ' ' && *idRefs != '\0')
  1668. idRefs++;
  1669. /*
  1670. * skip the space to the next id.
  1671. */
  1672. while (*idRefs == ' ')
  1673. idRefs++;
  1674. /*
  1675. * now test to see if this is a match
  1676. * cycle if so. quit if the end of string
  1677. * or not a match.
  1678. */
  1679. } while (*idRefs != '\0' &&
  1680. _DtCvStrNCaseCmpLatin1(id, idRefs, len) == 0 &&
  1681. (idRefs[len] == ' ' || idRefs[len] == '\0'));
  1682. /*
  1683. * the next non-spanned column in this row will use this id.
  1684. */
  1685. row_specs[i].next_id = idRefs;
  1686. }
  1687. }
  1688. if (NULL != id && '\0' != *id)
  1689. *ptr = c;
  1690. thisCell->row_spn = count;
  1691. }
  1692. for (i = 0, cellWidth = 0; i < thisCell->col_spn; i++)
  1693. cellWidth += col_specs[myCol + i].actual;
  1694. /*
  1695. * set the start line and text information
  1696. */
  1697. SetBeginCounts(canvas, &(thisCell->info.cnt));
  1698. /*
  1699. * check to see if this cell is overhung by a previous cell.
  1700. * If so, zero the top margin. But remember and restore it
  1701. * because resizing may eliminate the need for the overhang!
  1702. */
  1703. if (&BlankTableCell != thisCell->cell_seg)
  1704. {
  1705. saveTop = _DtCvContainerTMarginOfSeg(thisCell->cell_seg);
  1706. if (_DtCvTRUE == col_specs[myCol].hanger
  1707. && 0 != row_specs[row].y_adj && myCol > row_specs[row].column)
  1708. _DtCvContainerTMarginOfSeg(thisCell->cell_seg) = 0;
  1709. }
  1710. /*
  1711. * Format the cell
  1712. */
  1713. FormatCell(canvas, layout, thisCell->cell_seg, cellWidth,
  1714. row_specs[row].height, basePt,
  1715. &brdCnt, &retWidth, &retHeight, &retTabFlag);
  1716. if (&BlankTableCell != thisCell->cell_seg)
  1717. _DtCvContainerTMarginOfSeg(thisCell->cell_seg) = saveTop;
  1718. /*
  1719. * set some ending information
  1720. */
  1721. thisCell->info.height = retHeight;
  1722. thisCell->info.width = retWidth;
  1723. SetEndCounts(canvas, &(thisCell->info.cnt), brdCnt);
  1724. /*
  1725. * check the height against previous heights
  1726. */
  1727. if (row_specs[row].height < retHeight && thisCell->row_spn == 1)
  1728. row_specs[row].height = retHeight;
  1729. /*
  1730. * check for run over of the desired widths
  1731. */
  1732. if (retWidth > cellWidth)
  1733. {
  1734. register int j;
  1735. _DtCvUnit cellMax;
  1736. _DtCvUnit maxSlop;
  1737. _DtCvUnit value;
  1738. _DtCvUnit percent;
  1739. _DtCvUnit slopUsed = 0;
  1740. _DtCvUnit slop = retWidth - cellWidth; /* the amount of room
  1741. required of the neighbors */
  1742. /*
  1743. * set the reformat flag
  1744. */
  1745. if (False == retTabFlag)
  1746. reformat = True;
  1747. /*
  1748. * determine the maximum size the column can occupy
  1749. */
  1750. for (j = 0, cellMax = 0;
  1751. j < thisCell->col_spn && j + myCol < max_cols; j++)
  1752. cellMax += col_specs[myCol+j].max;
  1753. /*
  1754. * determine the maximum available space from the neighbors.
  1755. */
  1756. for (j = myCol + thisCell->col_spn, maxSlop = 0; j < max_cols; j++)
  1757. maxSlop = maxSlop + col_specs[j].actual - col_specs[j].min;
  1758. /*
  1759. * If the slop demanded is larger than available,
  1760. * simply reduced the other column specifications to their smallest
  1761. * values.
  1762. */
  1763. if (slop >= maxSlop)
  1764. {
  1765. for (j = myCol + thisCell->col_spn; j < max_cols; j++)
  1766. col_specs[j].actual = col_specs[j].min;
  1767. /*
  1768. * Is it allowed for this column to 'hang over' the others?
  1769. *
  1770. * And is it the first one? I.e. don't allow more than one
  1771. * cell per row to overhang it's neighbors.
  1772. *
  1773. * And only allow it if the vertical text justification places
  1774. * the text at the top of the cell.
  1775. */
  1776. if (_DtCvTRUE == col_specs[myCol].hanger
  1777. && 0 == row_specs[row].y_adj
  1778. && _DtCvJUSTIFY_TOP == TxtVertJustify(thisCell->cell_seg))
  1779. {
  1780. /*
  1781. * now set the other columns to start a little lower
  1782. * in their objects. Remove the bottom margin from the
  1783. * adjustment. One would hope that each of the containers
  1784. * for the columns in the row have the same bottom margin
  1785. * so that the overhung cell will push the next row down
  1786. * by the appropriate amount.
  1787. */
  1788. row_specs[row].y_adj = retHeight -
  1789. _DtCvContainerBMarginOfSeg(thisCell->cell_seg);
  1790. row_specs[row].column = myCol;
  1791. retWidth = cellMax;
  1792. /*
  1793. * clear the reformat flag
  1794. */
  1795. reformat = False;
  1796. }
  1797. }
  1798. else if (slop > 0)
  1799. {
  1800. /*
  1801. * the maximum slop available from the neighbors is
  1802. * enough. Now take space from my neighbors based
  1803. * on their orginal size. I.e. the larger they
  1804. * are, the more I take from them.
  1805. */
  1806. for (j = myCol + thisCell->col_spn; j < max_cols; j++)
  1807. {
  1808. percent = col_specs[j].actual - col_specs[j].min;
  1809. value = slop * percent / maxSlop;
  1810. slopUsed += value;
  1811. col_specs[j].actual -= value;
  1812. }
  1813. /*
  1814. * if any more slop is needed, grab it on a strictly
  1815. * straight basis.
  1816. */
  1817. do {
  1818. slop -= slopUsed;
  1819. for (j = myCol + thisCell->col_spn, slopUsed = 0;
  1820. slop > slopUsed && j < max_cols; j++)
  1821. {
  1822. if (col_specs[j].actual > col_specs[j].min)
  1823. {
  1824. col_specs[j].actual--;
  1825. slopUsed++;
  1826. }
  1827. }
  1828. } while (slopUsed > 0 && slop > slopUsed);
  1829. }
  1830. /*
  1831. * set the column width in the controlling column struct.
  1832. */
  1833. if (thisCell->col_spn == 1)
  1834. {
  1835. col_specs[myCol].actual = retWidth;
  1836. }
  1837. else
  1838. {
  1839. /*
  1840. * how much to spread among the columns?
  1841. */
  1842. slop = cellMax - retWidth;
  1843. /*
  1844. * if the aggragate max width is smaller than required,
  1845. * allocate the excess among the columns.
  1846. */
  1847. if (slop < 0)
  1848. {
  1849. /*
  1850. * set the desired to the max and calculate the leftover
  1851. * slop and the maximum desired size.
  1852. */
  1853. for (j = 0, slop = retWidth, maxSlop = 0;
  1854. myCol + j < max_cols && j < thisCell->col_spn; j++)
  1855. {
  1856. col_specs[j].actual = col_specs[myCol + j].max;
  1857. slop -= col_specs[myCol + j].max;
  1858. maxSlop += col_specs[myCol + j].max;
  1859. }
  1860. /*
  1861. * now allocate the leftover slop to each colum
  1862. * based on the maximum desired size.
  1863. */
  1864. for (j = 0, slopUsed = 0;
  1865. slop > slopUsed && myCol + j < max_cols
  1866. && j < thisCell->col_spn; j++)
  1867. {
  1868. value = slop * col_specs[myCol + j].max / maxSlop;
  1869. if (((slop*col_specs[myCol+j].max) % maxSlop) >= (maxSlop/2))
  1870. value++;
  1871. col_specs[myCol + j].actual += value;
  1872. slopUsed += value;
  1873. }
  1874. }
  1875. else if (slop > 0)
  1876. {
  1877. slopUsed = 0;
  1878. for (j = myCol;
  1879. j < max_cols && j < myCol + thisCell->col_spn; j++)
  1880. {
  1881. percent = col_specs[j].max - col_specs[j].actual;
  1882. value = slop * percent / maxSlop;
  1883. slopUsed += value;
  1884. col_specs[j].actual += value;
  1885. }
  1886. do {
  1887. slop -= slopUsed;
  1888. for (j = myCol, slopUsed = 0; slop > slopUsed &&
  1889. j < max_cols && j < myCol + thisCell->col_spn; j++)
  1890. {
  1891. if (col_specs[j].actual < col_specs[j].max)
  1892. {
  1893. col_specs[j].actual++;
  1894. slopUsed++;
  1895. }
  1896. }
  1897. } while (slopUsed > 0 && slop > slopUsed);
  1898. }
  1899. else /* if (slop == 0) */
  1900. {
  1901. for (j = 0; myCol + j < max_cols && j < thisCell->col_spn; j++)
  1902. col_specs[j].actual = col_specs[myCol + j].max;
  1903. }
  1904. }
  1905. }
  1906. return reformat;
  1907. }
  1908. /******************************************************************************
  1909. * Function: ProcessTable
  1910. *
  1911. *****************************************************************************/
  1912. static void
  1913. ProcessTable(
  1914. _DtCanvasStruct *canvas,
  1915. LayoutInfo *layout,
  1916. _DtCvSegmentI *table,
  1917. _DtCvUnit min_y)
  1918. {
  1919. int a;
  1920. int b;
  1921. int c;
  1922. int col;
  1923. int row;
  1924. int cell;
  1925. int divisor;
  1926. int maxCols;
  1927. int maxRows;
  1928. int maxRowSpn;
  1929. int saveLnStart = canvas->line_cnt;
  1930. int saveTxtStart = canvas->txt_cnt;
  1931. int saveTravCnt = canvas->trav_cnt;
  1932. _DtCvUnit workWidth;
  1933. _DtCvUnit newLeft;
  1934. _DtCvUnit saveLeft = layout->left;
  1935. _DtCvUnit saveYpos = layout->info.y_pos;
  1936. _DtCvUnit tableYpos;
  1937. _DtCvUnit newHeight;
  1938. _DtCvUnit newWidth;
  1939. _DtCvUnit oldAlignPos;
  1940. short anchorRow = -1;
  1941. const char **widthStr;
  1942. const char *saveAlignChar = layout->info.align_char;
  1943. char **rowIds;
  1944. char *alignCharacters = NULL;
  1945. char alignBuf[16];
  1946. _DtCvFrmtOption saveTxtJustify = layout->txt_justify;
  1947. _DtCvFrmtOption colJustify = _DtCvJUSTIFY_LEFT;
  1948. _DtCvFrmtOption *colJustSpec;
  1949. _DtCvValue oldFound = layout->id_found;
  1950. _DtCvValue haveBrds = False;
  1951. _DtCvValue saveState = layout->table_flag;
  1952. _DtCvValue saveAlignFlag = layout->info.align_flag;
  1953. _DtCvValue saveAlignPos = layout->info.align_pos;
  1954. _DtCvValue redo;
  1955. CellInfo defCell;
  1956. CellInfo *cellInfo = &defCell;
  1957. ColumnSpec defColumn;
  1958. ColumnSpec *colSpecs = &defColumn;
  1959. RowSpec defRow;
  1960. RowSpec *rowSpecs = &defRow;
  1961. DataPoint basePt;
  1962. GrpInfo grpInfo = DefGrpInfo;
  1963. /*
  1964. * get the base margins that the table will be working in.
  1965. */
  1966. GetCurrentDataPoint(layout, &basePt);
  1967. /*
  1968. * find out how many rows there are.
  1969. */
  1970. for (rowIds = _DtCvCellIdsOfTableSeg(table), maxRows = 0;
  1971. rowIds != NULL && rowIds[maxRows] != NULL; maxRows++);
  1972. if (maxRows == 0)
  1973. return;
  1974. /*
  1975. * get the number of columns and the column widths
  1976. */
  1977. maxCols = _DtCvNumColsOfTableSeg(table);
  1978. widthStr = (const char **)_DtCvColWOfTableSeg(table);
  1979. colJustSpec = _DtCvColJustifyOfTableSeg(table);
  1980. if (maxCols < 1)
  1981. maxCols = 1;
  1982. if (widthStr == NULL)
  1983. widthStr = DefWidth;
  1984. /*
  1985. * determine the width the table has to work with.
  1986. */
  1987. workWidth = layout->max_width - basePt.left - basePt.right -
  1988. layout->left - layout->right;
  1989. if (workWidth < 0)
  1990. workWidth = 0;
  1991. /*
  1992. * turn the string specifying column widths into units.
  1993. */
  1994. if (maxCols != 1)
  1995. {
  1996. colSpecs = (ColumnSpec *) malloc (sizeof(ColumnSpec) * maxCols);
  1997. if (colSpecs == NULL)
  1998. return;
  1999. }
  2000. if (maxRows != 1)
  2001. {
  2002. rowSpecs = (RowSpec *) malloc (sizeof(RowSpec) * maxRows);
  2003. if (rowSpecs == NULL)
  2004. {
  2005. if (maxCols > 1)
  2006. free(colSpecs);
  2007. return;
  2008. }
  2009. }
  2010. if (maxRows != 1 || maxCols != 1)
  2011. {
  2012. cellInfo = (CellInfo *) malloc (sizeof(CellInfo) * maxCols * maxRows);
  2013. if (cellInfo == NULL)
  2014. {
  2015. if (maxCols > 1)
  2016. free(colSpecs);
  2017. if (maxRows > 1)
  2018. free(rowSpecs);
  2019. return;
  2020. }
  2021. }
  2022. /*
  2023. * for each column, process the width specification.
  2024. * '+Optimal,Take,Give'
  2025. *
  2026. * + - means the cell can 'hang over' its neighbors.
  2027. * It will take everything it can get and then
  2028. * push the other below it. (Labeled lists).
  2029. * Optimal - The desired percentage of the available space to
  2030. * use for the column.
  2031. * Take - The percentage amount the column will take from
  2032. * other columns to make itself 'fit'.
  2033. * Give - The percentage amount the column is willing to give up
  2034. * to other columns for them to 'fit'.
  2035. */
  2036. for (col = 0, divisor = 0; col < maxCols; col++)
  2037. {
  2038. const char *nxtWidth = *widthStr;
  2039. /*
  2040. * move to the meat of the width specification string.
  2041. */
  2042. SkipToNumber(&nxtWidth);
  2043. /*
  2044. * set the correct 'allow hangers' flag.
  2045. */
  2046. colSpecs[col].hanger = _DtCvFALSE;
  2047. if ('+' == *nxtWidth)
  2048. {
  2049. colSpecs[col].hanger = _DtCvTRUE;
  2050. nxtWidth++;
  2051. }
  2052. /*
  2053. * now process the O,G,T specification.
  2054. */
  2055. a = GetValueFromString(&nxtWidth, 1); if (a < 1) a = 1;
  2056. b = GetValueFromString(&nxtWidth, 0); if (b < 0) b = 0;
  2057. c = GetValueFromString(&nxtWidth, b); if (c > a) c = a;
  2058. /*
  2059. * for now just get the base percentages.
  2060. */
  2061. colSpecs[col].min = a - c;
  2062. colSpecs[col].actual = a;
  2063. colSpecs[col].max = a + b;
  2064. /*
  2065. * get the column justification.
  2066. */
  2067. if (NULL != colJustSpec)
  2068. {
  2069. colJustify = *colJustSpec;
  2070. colJustSpec++;
  2071. }
  2072. colSpecs[col].justify = colJustify;
  2073. if (_DtCvINHERIT == colJustify)
  2074. colSpecs[col].justify = saveTxtJustify;
  2075. /*
  2076. * up the divisor value.
  2077. */
  2078. divisor += colSpecs[col].actual;
  2079. /*
  2080. * skip to the next set of width specifications
  2081. */
  2082. if (col + 1 < maxCols && NULL != widthStr[1])
  2083. widthStr++;
  2084. /*
  2085. * initialize the cell information for the rows in this column
  2086. */
  2087. for (row = 0; row < maxRows; row++)
  2088. {
  2089. cellInfo[row * maxCols + col].cell_seg = NULL;
  2090. cellInfo[row * maxCols + col].col_spn = 0;
  2091. cellInfo[row * maxCols + col].row_spn = 0;
  2092. cellInfo[row * maxCols + col].info = DefLayFrmtInfo;
  2093. }
  2094. }
  2095. /*
  2096. * initialize the row specs
  2097. */
  2098. newHeight = 0;
  2099. if (-1 != min_y && 1 == maxRows)
  2100. newHeight = min_y - saveYpos;
  2101. for (row = 0; row < maxRows; row++)
  2102. {
  2103. rowSpecs[row].column = -1;
  2104. rowSpecs[row].y_adj = 0;
  2105. rowSpecs[row].height = newHeight;
  2106. rowSpecs[row].height = newHeight;
  2107. rowSpecs[row].next_id = rowIds[row];
  2108. }
  2109. /*
  2110. * now figure the real values
  2111. */
  2112. if (divisor < 1)
  2113. divisor = 1;
  2114. for (col = 0; col < maxCols; col++)
  2115. {
  2116. colSpecs[col].min = workWidth * colSpecs[col].min / divisor;
  2117. colSpecs[col].actual = workWidth * colSpecs[col].actual / divisor;
  2118. colSpecs[col].max = workWidth * colSpecs[col].max / divisor;
  2119. if (colSpecs[col].min < 1)
  2120. colSpecs[col].min = 1;
  2121. if (colSpecs[col].actual < 1)
  2122. colSpecs[col].actual = 1;
  2123. if (colSpecs[col].max < 1)
  2124. colSpecs[col].max = 1;
  2125. }
  2126. /*
  2127. * now process the table.
  2128. */
  2129. tableYpos = layout->info.y_pos;
  2130. maxRowSpn = 1;
  2131. alignCharacters = _DtCvJustifyCharsOfTableSeg(table);
  2132. /*
  2133. * set up the state of table processing and
  2134. * the beginning line/text counts.
  2135. */
  2136. layout->table_flag = True;
  2137. SetBeginCounts(canvas, &(grpInfo.cnt));
  2138. /*
  2139. * now process each column, row by row.
  2140. * Doing it row by row allows the columns to shake out their
  2141. * sizing with less reformatting.
  2142. */
  2143. for (col = 0; col < maxCols; col++)
  2144. {
  2145. /*
  2146. * remember where this column starts.
  2147. */
  2148. saveTravCnt = canvas->trav_cnt;
  2149. saveLnStart = canvas->line_cnt;
  2150. saveTxtStart = canvas->txt_cnt;
  2151. newLeft = layout->left;
  2152. colJustify = layout->txt_justify;
  2153. layout->txt_justify = colSpecs[col].justify;
  2154. /*
  2155. * initialize the JUSTIFY_NUM or JUSTIFY_CHAR information
  2156. */
  2157. layout->info.align_pos = 0;
  2158. layout->info.align_char = PeriodStr;
  2159. if (_DtCvJUSTIFY_CHAR == layout->txt_justify)
  2160. {
  2161. /*
  2162. * are any alignment characters specified?
  2163. */
  2164. if (NULL != alignCharacters && '\0' != alignCharacters)
  2165. {
  2166. int len = mblen(alignCharacters, MB_CUR_MAX);
  2167. /*
  2168. * copy the character into a buffer
  2169. */
  2170. strncpy(alignBuf, alignCharacters, len);
  2171. alignBuf[len] = '\0';
  2172. layout->info.align_char = alignBuf;
  2173. /*
  2174. * are there more characters? If so increment for the
  2175. * next column that may have JUSTIFY_CHAR. Otherwise,
  2176. * leave alone and re-use for other columns.
  2177. */
  2178. if ('\0' != alignCharacters[len])
  2179. alignCharacters += len;
  2180. }
  2181. /* no...then default */
  2182. else
  2183. layout->txt_justify = _DtCvJUSTIFY_LEFT;
  2184. }
  2185. do {
  2186. /*
  2187. * reset the counts to the start
  2188. */
  2189. canvas->trav_cnt = saveTravCnt;
  2190. canvas->line_cnt = saveLnStart;
  2191. canvas->txt_cnt = saveTxtStart;
  2192. layout->left = newLeft;
  2193. /*
  2194. * for each row, format the cell in this columns
  2195. */
  2196. for (row = 0, redo = False, cell = col;
  2197. row < maxRows && redo == False;
  2198. row++, cell += maxCols)
  2199. {
  2200. /*
  2201. * remember the old height
  2202. */
  2203. rowSpecs[row].lst_height = rowSpecs[row].height;
  2204. /*
  2205. * set the alignment flag for each column in the row.
  2206. */
  2207. layout->info.align_flag = False;
  2208. if (_DtCvJUSTIFY_CHAR == layout->txt_justify ||
  2209. _DtCvJUSTIFY_NUM == layout->txt_justify)
  2210. layout->info.align_flag = True;
  2211. /*
  2212. * remember the alignment position
  2213. */
  2214. oldAlignPos = layout->info.align_pos;
  2215. /*
  2216. * layout all the cells jammed to the top of the table.
  2217. * later, they get moved down to their position.
  2218. */
  2219. layout->info.y_pos = tableYpos;
  2220. redo = ResolveCell(canvas, layout, table,
  2221. colSpecs, rowSpecs, col, row,
  2222. maxCols, maxRows, cellInfo);
  2223. /*
  2224. * check for maximum row span
  2225. */
  2226. if (maxRowSpn < cellInfo[cell].row_spn)
  2227. maxRowSpn = cellInfo[cell].row_spn;
  2228. /*
  2229. * did the cell have borders?
  2230. */
  2231. if (0 != cellInfo[cell].info.cnt.my_lines)
  2232. haveBrds = True;
  2233. /*
  2234. * check to see if the specified anchor has been found in
  2235. * this row. If so, save some information for later use.
  2236. */
  2237. if (anchorRow == -1 && oldFound != layout->id_found)
  2238. anchorRow = row;
  2239. /*
  2240. * check to see if the alignment position has changed.
  2241. * for all but the first row!
  2242. */
  2243. if (0 != row && oldAlignPos != layout->info.align_pos)
  2244. redo = True;
  2245. }
  2246. if (True == redo)
  2247. {
  2248. for (a = 0; a < row; a++)
  2249. {
  2250. /*
  2251. * restore the old row heights for this column
  2252. */
  2253. rowSpecs[a].height = rowSpecs[a].lst_height;
  2254. /*
  2255. * reset the hanging cell information.
  2256. */
  2257. if (col == rowSpecs[a].column)
  2258. {
  2259. rowSpecs[a].column = -1;
  2260. rowSpecs[a].y_adj = 0;
  2261. }
  2262. }
  2263. }
  2264. } while (redo == True);
  2265. /*
  2266. * push the next column to the right by size of this column
  2267. */
  2268. layout->left += colSpecs[col].actual;
  2269. /*
  2270. * restore the horizontal text justification
  2271. */
  2272. layout->txt_justify = colJustify;
  2273. }
  2274. /*
  2275. * set the ending counts for the lines/text in the table.
  2276. * and save the information as long as we are not a table
  2277. * that is a descendant of some container with a border and
  2278. * our cells include borders and we're going to have to honor
  2279. * boundaries.
  2280. */
  2281. SetEndCounts(canvas, &(grpInfo.cnt), 0);
  2282. if (_DtCvUSE_BOUNDARY_MOVE == canvas->constraint &&
  2283. False == layout->brdr_flag && True == haveBrds)
  2284. {
  2285. GrpInfo *info = (GrpInfo *) malloc (sizeof(GrpInfo));
  2286. /*
  2287. * warning - nothing done if malloc error.
  2288. */
  2289. if (NULL != info)
  2290. {
  2291. /*
  2292. * initialize to the line counts for the table
  2293. */
  2294. *info = grpInfo;
  2295. /*
  2296. * set the linked list information
  2297. */
  2298. info->next_info = layout->grp_lst;
  2299. layout->grp_lst = info;
  2300. }
  2301. }
  2302. /*
  2303. * Now go back and search for zeroed row heights and fill them in
  2304. * based on spanned rows. This can only happen if maxRowSpn is
  2305. * greater than 1! Otherwise, a row height really did end up zero!
  2306. */
  2307. if (maxRowSpn > 1)
  2308. {
  2309. /*
  2310. * try to resolve the zero height rows
  2311. */
  2312. for (a = 1, redo = True; redo && a < maxRowSpn; a++)
  2313. {
  2314. redo = False;
  2315. for (row = 0; row < maxRows; row++)
  2316. {
  2317. if (rowSpecs[row].height == 0 &&
  2318. ResolveHeight(rowSpecs, cellInfo, maxCols, row, a) == 0)
  2319. redo = True;
  2320. }
  2321. }
  2322. /*
  2323. * if any of the rows comes up unresolved, force to an average
  2324. * line height.
  2325. *
  2326. * But only do this if the first cell *does not* span all the rows
  2327. * and columns.
  2328. */
  2329. if (redo &&
  2330. cellInfo[0].row_spn != maxRows && cellInfo[0].col_spn != maxCols)
  2331. {
  2332. for (row = 0; row < maxRows; row++)
  2333. {
  2334. if (rowSpecs[row].height == 0)
  2335. rowSpecs[row].height = canvas->metrics.line_height;
  2336. }
  2337. }
  2338. /*
  2339. * Now, double check that the row heights will accomodate
  2340. * all the cells.
  2341. */
  2342. for (row = 0; row < maxRows; row++)
  2343. for (col = 0; col < maxCols; col++)
  2344. AdjustHeight(cellInfo, rowSpecs, maxCols, row, col);
  2345. }
  2346. /*
  2347. * now check that the minimum heights used for the rows matches
  2348. * or exceeds the minimum y position required.
  2349. */
  2350. if (-1 != min_y)
  2351. {
  2352. _DtCvUnit pad;
  2353. for (newHeight = 0, row = 0; row < maxRows; row++)
  2354. newHeight += rowSpecs[row].height;
  2355. if (tableYpos + newHeight < min_y)
  2356. {
  2357. newHeight = tableYpos - min_y;
  2358. for (row = 0; 0 < newHeight && row < maxRows; row++)
  2359. {
  2360. pad = (newHeight/(maxRows-row));
  2361. rowSpecs[row].height += pad;
  2362. newHeight -= pad;
  2363. }
  2364. }
  2365. }
  2366. /*
  2367. * now reposition the cells based on the final row heights.
  2368. */
  2369. layout->info.y_pos = tableYpos;
  2370. for (tableYpos = 0, cell = 0, row = 0; row < maxRows;
  2371. tableYpos = tableYpos + rowSpecs[row].height + rowSpecs[row].y_adj,
  2372. row++)
  2373. {
  2374. /*
  2375. * check to see if the specified anchor has been found in this
  2376. * row. If so, adjust the found position.
  2377. */
  2378. if (anchorRow == row)
  2379. layout->id_Ypos += tableYpos;
  2380. for (col = 0, layout->left = saveLeft; col < maxCols;
  2381. layout->left += colSpecs[col++].actual, cell++)
  2382. {
  2383. if (cellInfo[cell].cell_seg != NULL)
  2384. {
  2385. /*
  2386. * calculate the new height
  2387. */
  2388. for (newHeight = 0, a = 0; a < cellInfo[cell].row_spn; a++)
  2389. {
  2390. newHeight += rowSpecs[row + a].height;
  2391. if (col != rowSpecs[row + a].column)
  2392. newHeight += rowSpecs[row + a].y_adj;
  2393. }
  2394. /*
  2395. * calculate the new width.
  2396. */
  2397. for (newWidth = 0, a = 0; a < cellInfo[cell].col_spn; a++)
  2398. newWidth += colSpecs[col + a].actual;
  2399. /*
  2400. * now get the overhang space for this cell
  2401. */
  2402. workWidth = 0;
  2403. if (col > rowSpecs[row].column)
  2404. workWidth = rowSpecs[row].y_adj;
  2405. /*
  2406. * if the heights (and/or width for spanning columns)
  2407. * are different, check to see if the
  2408. * cell contains lines that may be affected by the
  2409. * height adjustment.
  2410. *
  2411. * It is strongly assumed that if a table specifies that
  2412. * a cell can hang over it's neighbors that it will *NOT*
  2413. * have borders (whereby LinesMayChange is false) and
  2414. * newWidth will not be greater than the cell's width.
  2415. */
  2416. if ((newHeight > cellInfo[cell].info.height &&
  2417. True == LinesMayChange(canvas,
  2418. cellInfo[cell].info.cnt.beg_ln,
  2419. cellInfo[cell].info.cnt.end_ln,
  2420. cellInfo[cell].info.cnt.my_lines))
  2421. ||
  2422. (1 < cellInfo[cell].col_spn &&
  2423. newWidth > cellInfo[cell].info.width))
  2424. ReFormatCell(canvas, layout, &cellInfo[cell], colSpecs,
  2425. col, newHeight,
  2426. layout->info.y_pos + tableYpos);
  2427. else
  2428. /* adjust the cell rather than reformatting */
  2429. AdjustObjectPosition(canvas, layout,
  2430. TxtVertJustify(cellInfo[cell].cell_seg),
  2431. cellInfo[cell].info.cnt.beg_txt ,
  2432. cellInfo[cell].info.cnt.beg_ln ,
  2433. cellInfo[cell].info.cnt.beg_brk ,
  2434. cellInfo[cell].info.cnt.end_txt ,
  2435. cellInfo[cell].info.cnt.end_ln ,
  2436. cellInfo[cell].info.cnt.end_brk ,
  2437. cellInfo[cell].info.cnt.my_lines,
  2438. newHeight - cellInfo[cell].info.height,
  2439. 0,
  2440. tableYpos, workWidth);
  2441. }
  2442. }
  2443. }
  2444. /*
  2445. * increment the maximum y.
  2446. */
  2447. layout->info.y_pos += tableYpos;
  2448. layout->left = saveLeft;
  2449. if (maxCols > 1)
  2450. free(colSpecs);
  2451. if (maxRows > 1)
  2452. free(rowSpecs);
  2453. if (maxRows > 1 || maxCols > 1)
  2454. free(cellInfo);
  2455. layout->txt_justify = saveTxtJustify;
  2456. layout->table_flag = saveState;
  2457. /*
  2458. * restore the alignment information
  2459. */
  2460. layout->info.align_flag = saveAlignFlag;
  2461. layout->info.align_char = saveAlignChar;
  2462. layout->info.align_pos = saveAlignPos;
  2463. }
  2464. /******************************************************************************
  2465. * Function: UpdateDimensionArrays
  2466. *
  2467. * Purpose: Based on the object's orientation and justification,
  2468. * update the correct dimension array(s).
  2469. *
  2470. *****************************************************************************/
  2471. static void
  2472. UpdateDimensionArrays(
  2473. _DtCvSegmentI *p_seg,
  2474. _DtCvUnit width,
  2475. _DtCvUnit height,
  2476. TopDims *top_bot,
  2477. SideDims *side,
  2478. CornerDims *corner,
  2479. FlowDims *flow,
  2480. _DtCvUnit *max_left,
  2481. _DtCvUnit *max_right)
  2482. {
  2483. int i;
  2484. int j;
  2485. int *marginPtr;
  2486. _DtCvFrmtOption orient = ObjHorizOrient(p_seg);
  2487. _DtCvFrmtOption vOrient = ObjVertOrient(p_seg);
  2488. /*
  2489. * modify the width that headSize should be
  2490. */
  2491. j = DIMS_LM;
  2492. i = DIMS_TOP;
  2493. switch (orient)
  2494. {
  2495. case _DtCvJUSTIFY_RIGHT_MARGIN:
  2496. j++;
  2497. case _DtCvJUSTIFY_CENTER:
  2498. j++;
  2499. case _DtCvJUSTIFY_LEFT_MARGIN:
  2500. if (vOrient == _DtCvJUSTIFY_BOTTOM)
  2501. i = DIMS_BOTTOM;
  2502. if ((*top_bot)[i][j][DIMS_WIDTH] < width)
  2503. (*top_bot)[i][j][DIMS_WIDTH] = width;
  2504. if (_DtCvWRAP_JOIN != _DtCvContainerFlowOfSeg(p_seg))
  2505. (*top_bot)[i][j][DIMS_HEIGHT] += height;
  2506. break;
  2507. }
  2508. /*
  2509. * check left & right margins.
  2510. */
  2511. marginPtr = max_left;
  2512. j = DIMS_LEFT;
  2513. i = DIMS_TOP;
  2514. switch(orient)
  2515. {
  2516. case _DtCvJUSTIFY_RIGHT_CORNER:
  2517. case _DtCvJUSTIFY_RIGHT:
  2518. j = DIMS_RIGHT;
  2519. marginPtr = max_right;
  2520. case _DtCvJUSTIFY_LEFT_CORNER:
  2521. case _DtCvJUSTIFY_LEFT:
  2522. if (vOrient != _DtCvJUSTIFY_TOP)
  2523. i++;
  2524. if (vOrient == _DtCvJUSTIFY_BOTTOM)
  2525. i++;
  2526. /*
  2527. * push i to zero or 4
  2528. */
  2529. if (orient == _DtCvJUSTIFY_RIGHT_CORNER ||
  2530. orient == _DtCvJUSTIFY_LEFT_CORNER)
  2531. {
  2532. if (i) i = DIMS_BC;
  2533. (*corner)[i][j] += height;
  2534. if (*marginPtr < width)
  2535. *marginPtr = width;
  2536. }
  2537. else if (_DtCvContainerFlowOfSeg(p_seg) != _DtCvWRAP)
  2538. {
  2539. (*side)[i][j] += height;
  2540. if (*marginPtr < width)
  2541. *marginPtr = width;
  2542. }
  2543. else
  2544. {
  2545. (*flow)[j][DIMS_HEIGHT] += height;
  2546. if ((*flow)[j][DIMS_WIDTH] < width)
  2547. (*flow)[j][DIMS_WIDTH] = width;
  2548. }
  2549. break;
  2550. }
  2551. }
  2552. /******************************************************************************
  2553. * Function: DetermineMaxDims
  2554. *
  2555. *****************************************************************************/
  2556. static void
  2557. DetermineMaxDims(
  2558. TopDims *top_bot,
  2559. CornerDims *corner,
  2560. _DtCvUnit left_margin,
  2561. _DtCvUnit right_margin,
  2562. _DtCvUnit *top_height,
  2563. _DtCvUnit *bot_height,
  2564. _DtCvUnit *max_width)
  2565. {
  2566. register int j;
  2567. _DtCvUnit topWidth;
  2568. _DtCvUnit botWidth;
  2569. /*
  2570. * now process all the information gathered about the (sub)headings
  2571. * to determine the bounding box for the (head) txt. Start by figuring
  2572. * out the maximums for the dimensions.
  2573. *
  2574. * figure the current top and bottom max widths.
  2575. */
  2576. topWidth = left_margin + right_margin;
  2577. botWidth = left_margin + right_margin;
  2578. *top_height = 0;
  2579. *bot_height = 0;
  2580. for (j = DIMS_LM; j <= DIMS_RM; j++)
  2581. {
  2582. topWidth = topWidth + (*top_bot)[DIMS_TOP] [j][DIMS_WIDTH];
  2583. botWidth = botWidth + (*top_bot)[DIMS_BOTTOM][j][DIMS_WIDTH];
  2584. if (*top_height < (*top_bot)[DIMS_TOP][j][DIMS_HEIGHT])
  2585. *top_height = (*top_bot)[DIMS_TOP][j][DIMS_HEIGHT];
  2586. if (*bot_height < (*top_bot)[DIMS_BOTTOM][j][DIMS_HEIGHT])
  2587. *bot_height = (*top_bot)[DIMS_BOTTOM][j][DIMS_HEIGHT];
  2588. }
  2589. /*
  2590. * for the maximum top and bottom heights, take into
  2591. * consideration the corner values
  2592. */
  2593. if (*top_height < (*corner)[DIMS_TC][DIMS_LEFT])
  2594. *top_height = (*corner)[DIMS_TC][DIMS_LEFT];
  2595. if (*top_height < (*corner)[DIMS_TC][DIMS_RIGHT])
  2596. *top_height = (*corner)[DIMS_TC][DIMS_RIGHT];
  2597. if (*bot_height < (*corner)[DIMS_BC][DIMS_LEFT])
  2598. *bot_height = (*corner)[DIMS_BC][DIMS_LEFT];
  2599. if (*bot_height < (*corner)[DIMS_BC][DIMS_RIGHT])
  2600. *bot_height = (*corner)[DIMS_BC][DIMS_RIGHT];
  2601. *max_width = topWidth;
  2602. if (*max_width < botWidth)
  2603. *max_width = botWidth;
  2604. }
  2605. /******************************************************************************
  2606. * Function: DetermineFlowConstraints
  2607. *
  2608. *****************************************************************************/
  2609. static void
  2610. DetermineFlowConstraints(
  2611. LayoutInfo *layout,
  2612. FlowDims flow_dims,
  2613. _DtCvUnit left_margin,
  2614. _DtCvUnit right_margin,
  2615. _DtCvUnit start_y,
  2616. DataPoint *left_pt,
  2617. DataPoint *right_pt)
  2618. {
  2619. _DtCvUnit leftSide = flow_dims[DIMS_LEFT][DIMS_HEIGHT];
  2620. _DtCvUnit rightSide = flow_dims[DIMS_RIGHT][DIMS_HEIGHT];
  2621. /*
  2622. * Now, if there is flowing text required, put points on the
  2623. * stack to indicate them.
  2624. */
  2625. left_margin += flow_dims[DIMS_LEFT][DIMS_WIDTH];
  2626. right_margin += flow_dims[DIMS_RIGHT][DIMS_WIDTH];
  2627. GetCurrentDataPoint(layout, left_pt);
  2628. GetCurrentDataPoint(layout, right_pt);
  2629. left_pt->left += left_margin;
  2630. left_pt->right += right_margin;
  2631. left_pt->y_pos = _CEFORMAT_ALL;
  2632. right_pt->left += left_margin;
  2633. right_pt->right += right_margin;
  2634. right_pt->y_pos = _CEFORMAT_ALL;
  2635. while (leftSide > 0 || rightSide > 0)
  2636. {
  2637. if (leftSide > 0)
  2638. {
  2639. if (rightSide == 0 || leftSide <= rightSide)
  2640. {
  2641. left_pt->right = right_margin;
  2642. left_pt->y_pos = start_y + leftSide;
  2643. if (leftSide != rightSide)
  2644. left_margin = 0;
  2645. leftSide = 0;
  2646. InsertDataPoint(layout, left_pt);
  2647. }
  2648. }
  2649. if (rightSide > 0)
  2650. {
  2651. if (leftSide == 0 || leftSide > rightSide)
  2652. {
  2653. right_pt->left = left_margin;
  2654. right_pt->y_pos = start_y + rightSide;
  2655. if (leftSide != rightSide)
  2656. right_margin = 0;
  2657. rightSide = 0;
  2658. InsertDataPoint(layout, right_pt);
  2659. }
  2660. }
  2661. }
  2662. }
  2663. /******************************************************************************
  2664. * Function: DetermineHeadPositioning
  2665. *
  2666. *****************************************************************************/
  2667. static void
  2668. DetermineHeadPositioning(
  2669. TopDims *top_bot,
  2670. SideDims *side,
  2671. CornerDims *corner,
  2672. FlowDims *flow,
  2673. _DtCvUnit start_y,
  2674. _DtCvUnit max_top,
  2675. _DtCvUnit block_size,
  2676. _DtCvUnit *ret_side_size)
  2677. {
  2678. int i;
  2679. _DtCvUnit leftSideHeight = 0;
  2680. _DtCvUnit rightSideHeight = 0;
  2681. _DtCvUnit sideHeight = 0;
  2682. /*
  2683. * determine the maximum side heights
  2684. */
  2685. for (i = DIMS_TOP; i <= DIMS_BOTTOM; i++)
  2686. {
  2687. leftSideHeight += (*side)[i][DIMS_LEFT];
  2688. rightSideHeight += (*side)[i][DIMS_RIGHT];
  2689. }
  2690. /*
  2691. * determine the maximum side height
  2692. */
  2693. sideHeight = block_size;
  2694. if (sideHeight < leftSideHeight)
  2695. sideHeight = leftSideHeight;
  2696. if (sideHeight < rightSideHeight)
  2697. sideHeight = rightSideHeight;
  2698. if (sideHeight < (*flow)[DIMS_LEFT][DIMS_HEIGHT])
  2699. sideHeight = (*flow)[DIMS_LEFT][DIMS_HEIGHT];
  2700. if (sideHeight < (*flow)[DIMS_RIGHT][DIMS_HEIGHT])
  2701. sideHeight = (*flow)[DIMS_RIGHT][DIMS_HEIGHT];
  2702. /*
  2703. * calculate the starting Y position for each of the positions
  2704. * reuse the arrays that were used to save the max dimension values.
  2705. */
  2706. for (i = DIMS_LM; i <= DIMS_RM; i++)
  2707. {
  2708. (*top_bot)[DIMS_TOP] [i][DIMS_YPOS] = start_y;
  2709. (*top_bot)[DIMS_BOTTOM][i][DIMS_YPOS] = start_y + max_top + sideHeight;
  2710. }
  2711. (*corner)[DIMS_TC][DIMS_LEFT] = start_y;
  2712. (*corner)[DIMS_TC][DIMS_RIGHT] = start_y;
  2713. (*corner)[DIMS_BC][DIMS_LEFT] = start_y + max_top + sideHeight;
  2714. (*corner)[DIMS_BC][DIMS_RIGHT] = start_y + max_top + sideHeight;
  2715. (*side)[DIMS_TOP][DIMS_LEFT] = start_y + max_top;
  2716. (*side)[DIMS_TOP][DIMS_RIGHT] = start_y + max_top;
  2717. (*flow)[DIMS_LEFT ][DIMS_YPOS] = start_y + max_top;
  2718. (*flow)[DIMS_RIGHT][DIMS_YPOS] = start_y + max_top;
  2719. (*side)[DIMS_CENTER][DIMS_LEFT] = start_y + max_top +
  2720. (sideHeight - (*side)[DIMS_CENTER][DIMS_LEFT]) / 2;
  2721. (*side)[DIMS_CENTER][DIMS_RIGHT] = start_y + max_top +
  2722. (sideHeight - (*side)[DIMS_CENTER][DIMS_RIGHT]) / 2;
  2723. (*side)[DIMS_BOTTOM][DIMS_LEFT] = start_y + max_top +
  2724. sideHeight - (*side)[DIMS_BOTTOM][DIMS_LEFT];
  2725. (*side)[DIMS_BOTTOM][DIMS_RIGHT] = start_y + max_top +
  2726. sideHeight - (*side)[DIMS_BOTTOM][DIMS_RIGHT];
  2727. if (ret_side_size != NULL)
  2728. *ret_side_size = sideHeight;
  2729. }
  2730. /******************************************************************************
  2731. * Function: AdjustHead
  2732. *
  2733. * Parameters:
  2734. * base_left Specifies the x position that the controller
  2735. * occupying 'left_margin' space would start
  2736. * at.
  2737. * block_width Specifies the body's width for which to
  2738. * center or align a controller with.
  2739. * left_margin Specifies the space used by a controller
  2740. * that is on the left side of the body.
  2741. * right_margin Specifies the space used by a controller
  2742. * on the right side of the body.
  2743. *
  2744. *****************************************************************************/
  2745. static void
  2746. AdjustHeadPosition(
  2747. _DtCanvasStruct *canvas,
  2748. LayoutInfo *layout,
  2749. _DtCvSegmentI *p_seg,
  2750. TopDims *top_bot,
  2751. SideDims *side,
  2752. CornerDims *corner,
  2753. FlowDims *flow,
  2754. LayFrmtInfo *info,
  2755. _DtCvUnit base_y,
  2756. _DtCvUnit base_left,
  2757. _DtCvUnit block_width,
  2758. _DtCvUnit left_margin,
  2759. _DtCvUnit right_margin)
  2760. {
  2761. int i = DIMS_TOP; /* also DIMS_TC */
  2762. int j = DIMS_LEFT; /* also DIMS_LM */
  2763. int divisor = 2;
  2764. _DtCvUnit adjustX = 0;
  2765. _DtCvUnit adjustY = 0;
  2766. _DtCvUnit newY = 0;
  2767. _DtCvUnit headWidth = info->width;
  2768. _DtCvFrmtOption orient = ObjHorizOrient(p_seg);
  2769. _DtCvFrmtOption vOrient = ObjVertOrient(p_seg);
  2770. if (_DtCvContainerPercentOfSeg(p_seg) == 10000
  2771. && orient == _DtCvJUSTIFY_CENTER
  2772. && TxtHorizJustify(p_seg) == _DtCvJUSTIFY_LEFT)
  2773. headWidth = block_width;
  2774. switch (orient)
  2775. {
  2776. case _DtCvJUSTIFY_RIGHT_MARGIN:
  2777. divisor = 1;
  2778. j++;
  2779. case _DtCvJUSTIFY_CENTER:
  2780. adjustX = (block_width - headWidth) / divisor;
  2781. j++;
  2782. case _DtCvJUSTIFY_LEFT_MARGIN:
  2783. adjustX += left_margin;
  2784. if (vOrient == _DtCvJUSTIFY_BOTTOM)
  2785. i = DIMS_BOTTOM;
  2786. newY = (*top_bot)[i][j][DIMS_YPOS];
  2787. (*top_bot)[i][j][DIMS_YPOS] += info->height;
  2788. break;
  2789. case _DtCvJUSTIFY_RIGHT_CORNER:
  2790. adjustX = block_width + left_margin;
  2791. j = DIMS_RIGHT;
  2792. case _DtCvJUSTIFY_LEFT_CORNER:
  2793. if (vOrient == _DtCvJUSTIFY_BOTTOM)
  2794. i = DIMS_BC;
  2795. newY = (*corner)[i][j];
  2796. (*corner)[i][j] += info->height;
  2797. break;
  2798. case _DtCvJUSTIFY_RIGHT:
  2799. adjustX = block_width + left_margin;
  2800. j = DIMS_RIGHT;
  2801. case _DtCvJUSTIFY_LEFT:
  2802. if (vOrient != _DtCvJUSTIFY_TOP)
  2803. i++;
  2804. if (vOrient == _DtCvJUSTIFY_BOTTOM)
  2805. i++;
  2806. if (_DtCvContainerFlowOfSeg(p_seg) == _DtCvWRAP)
  2807. {
  2808. if (orient == _DtCvJUSTIFY_LEFT)
  2809. adjustX += left_margin;
  2810. else
  2811. adjustX -= headWidth;
  2812. newY = (*flow)[j][DIMS_YPOS];
  2813. (*flow)[j][DIMS_YPOS] += info->height;
  2814. }
  2815. else
  2816. {
  2817. newY = (*side)[i][j];
  2818. (*side)[i][j] += info->height;
  2819. }
  2820. break;
  2821. }
  2822. adjustY = newY - base_y;
  2823. adjustX += base_left;
  2824. /*
  2825. * adjust the text positions
  2826. */
  2827. AdjustTextPositions(canvas, info->cnt.beg_txt, info->cnt.end_txt,
  2828. adjustX, adjustY);
  2829. /*
  2830. * adjust the lines positions
  2831. */
  2832. AdjustLinePositions(canvas, info->cnt.beg_ln, info->cnt.end_ln,
  2833. adjustX, adjustY);
  2834. /*
  2835. * adjust the page breaks, but only if necessary.
  2836. */
  2837. AdjustPgBrk(canvas, info->cnt.beg_brk, info->cnt.end_brk, adjustY);
  2838. }
  2839. /******************************************************************************
  2840. * Function: InitDimArrays
  2841. *
  2842. *****************************************************************************/
  2843. static void
  2844. InitDimArrays(
  2845. TopDims *top_bot,
  2846. SideDims *side,
  2847. CornerDims *corner,
  2848. FlowDims *flow)
  2849. {
  2850. int i;
  2851. int j;
  2852. for (i = DIMS_TOP; i <= DIMS_BOTTOM; i++)
  2853. {
  2854. for (j = DIMS_LM; j <= DIMS_RM; j++)
  2855. {
  2856. (*top_bot)[i][j][DIMS_WIDTH] = 0;
  2857. (*top_bot)[i][j][DIMS_HEIGHT] = 0;
  2858. }
  2859. for (j = DIMS_LEFT; j <= DIMS_RIGHT; j++)
  2860. (*side)[i][j] = 0;
  2861. }
  2862. for (i = DIMS_LEFT; i <= DIMS_RIGHT; i++)
  2863. {
  2864. for (j = DIMS_WIDTH; j <= DIMS_HEIGHT; j++)
  2865. {
  2866. (*corner)[i][j] = 0;
  2867. (*flow)[i][j] = 0;
  2868. }
  2869. }
  2870. }
  2871. /******************************************************************************
  2872. * Function: ProcessController
  2873. *****************************************************************************/
  2874. static LayFrmtInfo *
  2875. ProcessController(
  2876. _DtCanvasStruct *canvas,
  2877. LayoutInfo *layout,
  2878. _DtCvSegmentI *cur_seg)
  2879. {
  2880. int getLn;
  2881. int saveTravCnt = canvas->trav_cnt;
  2882. _DtCvUnit saveYPos = layout->info.y_pos;
  2883. _DtCvUnit saveMaxWidth = layout->max_width;
  2884. _DtCvUnit saveLeft = layout->left;
  2885. _DtCvUnit saveRight = layout->right;
  2886. _DtCvUnit maxWidth;
  2887. _DtCvUnit maxXPos;
  2888. _DtCvUnit myMaxWidth;
  2889. LayFrmtInfo *frmtInfo;
  2890. DataPoint basePt;
  2891. DataPoint zeroPt;
  2892. _DtCvValue redo;
  2893. /*
  2894. * Controllers always break the formatting sequence.
  2895. * So save any information in the buffer, reset the margins and
  2896. * add the appropriate lines, and check for going over boundaries.
  2897. */
  2898. CheckSaveInfo(canvas, layout, cur_seg, 0);
  2899. CheckFormat(layout, True);
  2900. /*
  2901. * Get the controller specific information.
  2902. * disallow some of the orientation & vOrient combinations
  2903. */
  2904. if ((ObjHorizOrient(cur_seg) == _DtCvJUSTIFY_CENTER
  2905. && ObjVertOrient(cur_seg) != _DtCvJUSTIFY_BOTTOM)
  2906. ||
  2907. (ObjVertOrient(cur_seg) == _DtCvJUSTIFY_CENTER
  2908. && ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_LEFT
  2909. && ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_RIGHT))
  2910. ObjVertOrient(cur_seg) = _DtCvJUSTIFY_TOP;
  2911. if (_DtCvContainerFlowOfSeg(cur_seg) == _DtCvWRAP
  2912. &&
  2913. (ObjVertOrient(cur_seg) != _DtCvJUSTIFY_TOP
  2914. ||
  2915. (ObjVertOrient(cur_seg) == _DtCvJUSTIFY_TOP
  2916. && ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_LEFT
  2917. && ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_RIGHT)))
  2918. _DtCvContainerFlowOfSeg(cur_seg) = _DtCvWRAP_NONE;
  2919. if (_DtCvContainerFlowOfSeg(cur_seg) == _DtCvWRAP_JOIN
  2920. &&
  2921. (ObjVertOrient(cur_seg) != _DtCvJUSTIFY_TOP
  2922. || ObjHorizOrient(cur_seg) != _DtCvJUSTIFY_LEFT_MARGIN))
  2923. {
  2924. ObjVertOrient(cur_seg) = _DtCvJUSTIFY_TOP;
  2925. ObjHorizOrient(cur_seg) = _DtCvJUSTIFY_LEFT_MARGIN;
  2926. }
  2927. /*
  2928. * malloc a formatting dimension structure and initialize it with
  2929. * default values. This will be returned to the caller.
  2930. */
  2931. frmtInfo = (LayFrmtInfo *) malloc (sizeof(LayFrmtInfo));
  2932. *frmtInfo = DefLayFrmtInfo;
  2933. /*
  2934. * the controller object begins here.
  2935. */
  2936. SetBeginCounts(canvas, &(frmtInfo->cnt));
  2937. /*
  2938. * set the parent's data point in the stack
  2939. */
  2940. GetCurrentDataPoint(layout, &basePt);
  2941. /*
  2942. * calculate the amount of space the controller can occupy.
  2943. * first calculate the amount of space to work with.
  2944. * then truncate to zero if necessary.
  2945. * then use the percentage of that remaining area as the space
  2946. * the controller's segments can occupy.
  2947. */
  2948. myMaxWidth = layout->max_width - basePt.left - basePt.right
  2949. - saveLeft - saveRight;
  2950. if (myMaxWidth < 0)
  2951. myMaxWidth = 0;
  2952. myMaxWidth = (_DtCvUnit) (((double) myMaxWidth)
  2953. * ((double) _DtCvContainerPercentOfSeg(cur_seg))
  2954. / HeadDivisor);
  2955. /*
  2956. * Format the controller at a 'zero'ed point.
  2957. * The lines it generates will be moved later to their correct position.
  2958. */
  2959. layout->left = 0;
  2960. layout->right = 0;
  2961. zeroPt = DefDataPt;
  2962. PushDataPoint(layout, &zeroPt);
  2963. /*
  2964. * now process as a regular container
  2965. */
  2966. do {
  2967. /*
  2968. * set some counts and flags (necessary for a redo).
  2969. */
  2970. redo = False;
  2971. canvas->trav_cnt = saveTravCnt;
  2972. canvas->line_cnt = frmtInfo->cnt.beg_ln;
  2973. canvas->txt_cnt = frmtInfo->cnt.beg_txt;
  2974. layout->max_width = myMaxWidth;
  2975. layout->info.y_pos = 0;
  2976. /*
  2977. * process the container
  2978. */
  2979. ProcessContainer(canvas,layout,cur_seg,-1,&maxWidth,&maxXPos,&getLn);
  2980. /*
  2981. * check to see if we need to reformat because the minimum size
  2982. * is larger than we asked for.
  2983. */
  2984. if (maxXPos + _DtCvContainerRMarginOfSeg(cur_seg) > myMaxWidth)
  2985. {
  2986. redo = True;
  2987. myMaxWidth = maxXPos + _DtCvContainerRMarginOfSeg(cur_seg);
  2988. }
  2989. } while (True == redo);
  2990. /*
  2991. * remove this element's data points from the stack.
  2992. */
  2993. RemoveDataPoint(layout, &zeroPt);
  2994. /*
  2995. * set the ending counts for the items in this container.
  2996. */
  2997. SetEndCounts(canvas, &(frmtInfo->cnt), getLn);
  2998. frmtInfo->width = myMaxWidth;
  2999. frmtInfo->height = layout->info.y_pos;
  3000. /*
  3001. * does this controller want to join with the lines in a non-controller?
  3002. */
  3003. if (_DtCvWRAP_JOIN == _DtCvContainerFlowOfSeg(cur_seg)
  3004. && frmtInfo->cnt.beg_txt != canvas->txt_cnt)
  3005. _DtCvSetJoinInfo(&(layout->info), True, canvas->txt_cnt - 1);
  3006. /*
  3007. * Restore the previous information
  3008. */
  3009. if (NULL != layout->lst_rendered)
  3010. layout->lst_rendered->next_disp = NULL;
  3011. layout->left = saveLeft;
  3012. layout->right = saveRight;
  3013. layout->max_width = saveMaxWidth;
  3014. layout->lst_rendered = NULL;
  3015. layout->info.y_pos = saveYPos;
  3016. return frmtInfo;
  3017. }
  3018. /******************************************************************************
  3019. * Function: AdjustForBorders
  3020. *
  3021. * Initializes the display line and graphic tables.
  3022. *****************************************************************************/
  3023. static void
  3024. AdjustForBorders(
  3025. _DtCanvasStruct *canvas,
  3026. LayoutInfo *layout,
  3027. _DtCvFrmtOption brdr,
  3028. _DtCvUnit line_width,
  3029. _DtCvUnit *ret_bot,
  3030. _DtCvUnit *ret_right)
  3031. {
  3032. /*
  3033. * if the line_width is zero, make it 1 so that is really takes
  3034. * up some space.
  3035. */
  3036. if (0 == line_width)
  3037. line_width = 1;
  3038. /*
  3039. * set the flag for processing a border
  3040. */
  3041. if (_DtCvBORDER_NONE != brdr)
  3042. layout->brdr_flag = True;
  3043. /*
  3044. * check to see if this element has a border. If so, adjust the
  3045. * boundaries.
  3046. */
  3047. if (brdr == _DtCvBORDER_FULL || brdr == _DtCvBORDER_HORZ
  3048. || brdr == _DtCvBORDER_TOP
  3049. || brdr == _DtCvBORDER_TOP_LEFT
  3050. || brdr == _DtCvBORDER_TOP_RIGHT)
  3051. layout->info.y_pos += line_width;
  3052. *ret_bot = 0;
  3053. if (brdr == _DtCvBORDER_FULL || brdr == _DtCvBORDER_HORZ
  3054. || brdr == _DtCvBORDER_BOTTOM
  3055. || brdr == _DtCvBORDER_BOTTOM_LEFT
  3056. || brdr == _DtCvBORDER_BOTTOM_RIGHT)
  3057. *ret_bot = line_width;
  3058. if (brdr == _DtCvBORDER_FULL || brdr == _DtCvBORDER_VERT
  3059. || brdr == _DtCvBORDER_LEFT
  3060. || brdr == _DtCvBORDER_TOP_LEFT
  3061. || brdr == _DtCvBORDER_BOTTOM_LEFT)
  3062. layout->left += line_width;
  3063. *ret_right = 0;
  3064. if (brdr == _DtCvBORDER_FULL || brdr == _DtCvBORDER_VERT
  3065. || brdr == _DtCvBORDER_RIGHT
  3066. || brdr == _DtCvBORDER_TOP_RIGHT
  3067. || brdr == _DtCvBORDER_BOTTOM_RIGHT)
  3068. {
  3069. layout->right += line_width;
  3070. *ret_right = line_width;
  3071. }
  3072. }
  3073. /******************************************************************************
  3074. * Function: DrawBorders
  3075. *
  3076. * Parameters:
  3077. * canvas Specifies the virtual canvas on which
  3078. * lines are drawn.
  3079. * layout Specifies the current layout information.
  3080. * brdr Specifies the type of border.
  3081. * top_y Specifes the top y of the bounding box for
  3082. * the object. Any border drawn should be
  3083. * completely below this y.
  3084. * bot_y Specifes the bottom y of the bounding box
  3085. * for the object. Any border drawn should be
  3086. * completely below this y.
  3087. * left_x Specifies the left x of the bounding box
  3088. * for the object. Any border drawn should be
  3089. * completely to the right of this x.
  3090. * right_x Specifies the right x of the bounding box
  3091. * for the object. Any border drawn should be
  3092. * completely to the left of this x.
  3093. *
  3094. * left_x right_x
  3095. * | |
  3096. * v v
  3097. * top_y ---> xxxxxxxxxxxxxxxxxxxxxx
  3098. * xxxxxxxxxxxxxxxxxxxxxx
  3099. * xx------------------xx
  3100. * xx| |xx (xx represents the line.)
  3101. * xx| |xx
  3102. * xx| |xx
  3103. * xx| |xx
  3104. * xx------------------xx
  3105. * bot_y ---> xxxxxxxxxxxxxxxxxxxxxx
  3106. * xxxxxxxxxxxxxxxxxxxxxx
  3107. *
  3108. *****************************************************************************/
  3109. static int
  3110. DrawBorders(
  3111. _DtCanvasStruct *canvas,
  3112. LayoutInfo *layout,
  3113. _DtCvFrmtOption brdr,
  3114. _DtCvPointer data,
  3115. _DtCvUnit line_width,
  3116. _DtCvUnit top_y,
  3117. _DtCvUnit bot_y,
  3118. _DtCvUnit left_x,
  3119. _DtCvUnit right_x)
  3120. {
  3121. int mod = 1;
  3122. int cnt = canvas->line_cnt;
  3123. _DtCvUnit width;
  3124. /*
  3125. * if line_width is zero, make it 1 so that it really takes
  3126. * up some space.
  3127. */
  3128. if (0 == line_width)
  3129. line_width = 1;
  3130. /*
  3131. * calculate the width of the element.
  3132. */
  3133. width = right_x - left_x;
  3134. /*
  3135. * If borders are specified, draw them
  3136. */
  3137. if (brdr != _DtCvBORDER_NONE)
  3138. {
  3139. /*
  3140. * now do the horizontal borders. the coordinates are the top,
  3141. * left most unit of the line.
  3142. */
  3143. switch(brdr)
  3144. {
  3145. case _DtCvBORDER_FULL:
  3146. case _DtCvBORDER_HORZ:
  3147. case _DtCvBORDER_BOTTOM:
  3148. case _DtCvBORDER_BOTTOM_LEFT:
  3149. case _DtCvBORDER_BOTTOM_RIGHT:
  3150. SaveLine(canvas, layout, _DtCvLINE_HORZ,
  3151. data, line_width,
  3152. left_x, bot_y, width);
  3153. mod = -1;
  3154. if (brdr == _DtCvBORDER_BOTTOM
  3155. || brdr == _DtCvBORDER_BOTTOM_LEFT
  3156. || brdr == _DtCvBORDER_BOTTOM_RIGHT)
  3157. break;
  3158. case _DtCvBORDER_TOP:
  3159. case _DtCvBORDER_TOP_LEFT:
  3160. case _DtCvBORDER_TOP_RIGHT:
  3161. SaveLine(canvas, layout, _DtCvLINE_HORZ,
  3162. data, line_width,
  3163. left_x, top_y, width);
  3164. }
  3165. /*
  3166. * for vertical lines, the coordinates are the top, right most
  3167. * unit of the line.
  3168. */
  3169. switch(brdr)
  3170. {
  3171. case _DtCvBORDER_FULL:
  3172. case _DtCvBORDER_BOTTOM_LEFT:
  3173. /*
  3174. * include the line width in length for a full
  3175. * border.
  3176. */
  3177. bot_y += line_width;
  3178. case _DtCvBORDER_VERT:
  3179. case _DtCvBORDER_LEFT:
  3180. case _DtCvBORDER_TOP_LEFT:
  3181. SaveLine(canvas, layout, _DtCvLINE_VERT,
  3182. data, line_width,
  3183. left_x, top_y, bot_y - top_y);
  3184. if (brdr == _DtCvBORDER_LEFT
  3185. || brdr == _DtCvBORDER_TOP_LEFT
  3186. || brdr == _DtCvBORDER_BOTTOM_LEFT)
  3187. break;
  3188. case _DtCvBORDER_BOTTOM_RIGHT:
  3189. /*
  3190. * if we didn't fall thru from above, we need to
  3191. * add the extension to the bottom to get the
  3192. * full length for the right vertical line.
  3193. */
  3194. if (brdr == _DtCvBORDER_BOTTOM_RIGHT)
  3195. bot_y += line_width;
  3196. case _DtCvBORDER_RIGHT:
  3197. case _DtCvBORDER_TOP_RIGHT:
  3198. SaveLine(canvas, layout, _DtCvLINE_VERT,
  3199. data, line_width,
  3200. right_x - line_width, top_y, bot_y - top_y);
  3201. }
  3202. }
  3203. return ((canvas->line_cnt - cnt) * mod);
  3204. }
  3205. /******************************************************************************
  3206. * Function: AdjustObjectPosition
  3207. *
  3208. * Parameters:
  3209. * canvas Specifies the virtual canvas on which
  3210. * lines are drawn.
  3211. * justify Specifies the vertical adjustment for the
  3212. * object.
  3213. * start_txt Specifies the start index of the text list.
  3214. * start_gr Specifies the start index of the graphics list.
  3215. * start_ln Specifies the start index of the line list.
  3216. * end_txt Specifies the end indext of the text list.
  3217. * end_gr Specifies the end indext of the graphics list.
  3218. * end_ln Specifies the end indext of the line list.
  3219. * height_adj Specifies the internal height adjust value.
  3220. * Depending on the justify type, this may
  3221. * add to y_adj for text and regions, bottom
  3222. * lines and the height of vertical lines.
  3223. * y_adj Specifies the y position adjustment.
  3224. * Lines, text and regions are moved this
  3225. * amount.
  3226. * internal_y Specifies the internal y position adjustment.
  3227. * height_adj includes this value. Text and
  3228. * regions are moved this amount.
  3229. *
  3230. * Return: nothing.
  3231. *
  3232. *****************************************************************************/
  3233. static void
  3234. AdjustObjectPosition(
  3235. _DtCanvasStruct *canvas,
  3236. LayoutInfo *layout,
  3237. _DtCvFrmtOption justify,
  3238. int start_txt,
  3239. int start_ln,
  3240. int start_brk,
  3241. int end_txt,
  3242. int end_ln,
  3243. int end_brk,
  3244. int brdr_cnt,
  3245. _DtCvUnit height_adj,
  3246. _DtCvUnit x_adj,
  3247. _DtCvUnit y_adj,
  3248. _DtCvUnit internal_y)
  3249. {
  3250. int mod = 1;
  3251. _DtCvUnit yOff = 0;
  3252. /*
  3253. * If border count is negative, indicates the first line in the
  3254. * list is bottom line. This requires special handling in adjusting
  3255. * its position. Set flags accordingly.
  3256. */
  3257. if (brdr_cnt < 0)
  3258. {
  3259. mod = -1;
  3260. brdr_cnt = -brdr_cnt;
  3261. }
  3262. /*
  3263. * calculate the offset value within the object for other objects
  3264. * contained in this object.
  3265. */
  3266. if (justify != _DtCvJUSTIFY_TOP)
  3267. {
  3268. yOff = height_adj - internal_y;
  3269. if (justify == _DtCvJUSTIFY_CENTER)
  3270. yOff /= 2;
  3271. }
  3272. yOff += y_adj;
  3273. yOff += internal_y;
  3274. /*
  3275. * don't modify the border lines around this object yet.
  3276. */
  3277. end_ln -= brdr_cnt;
  3278. /*
  3279. * modify the border lines of the objects contained within
  3280. * this object.
  3281. */
  3282. AdjustLinePositions(canvas, start_ln, end_ln, x_adj, yOff);
  3283. /*
  3284. * now adjust the border lines around this object.
  3285. */
  3286. start_ln = end_ln;
  3287. end_ln += brdr_cnt;
  3288. AdjustLinePositions(canvas, start_ln, end_ln, x_adj, y_adj);
  3289. /*
  3290. * now fix the lines if they've changed height and move
  3291. * the first line to its bottom position if necessary.
  3292. */
  3293. if (0 != height_adj)
  3294. {
  3295. while (start_ln < end_ln)
  3296. {
  3297. /*
  3298. * indicates the bottom line is the first line in the
  3299. * list. Move it down the height adjustment.
  3300. */
  3301. if (mod < 0)
  3302. {
  3303. canvas->line_lst[start_ln].pos_y += height_adj;
  3304. canvas->line_lst[start_ln].max_y += height_adj;
  3305. mod = 1;
  3306. }
  3307. /*
  3308. * stretch the vertical lines
  3309. */
  3310. else if (canvas->line_lst[start_ln].dir == _DtCvLINE_VERT)
  3311. canvas->line_lst[start_ln].max_y += height_adj;
  3312. start_ln++;
  3313. }
  3314. }
  3315. /*
  3316. * adjust the position of the text within this object.
  3317. */
  3318. AdjustTextPositions (canvas, start_txt, end_txt, x_adj, yOff);
  3319. /*
  3320. * adjust the position of the text within this object.
  3321. */
  3322. AdjustPgBrk (canvas, start_brk, end_brk, yOff);
  3323. }
  3324. /******************************************************************************
  3325. * Function: LinesMayChange
  3326. *
  3327. * Parameters:
  3328. * canvas Specifies the virtual canvas on which
  3329. * lines are drawn.
  3330. * start_ln Specifies the start index of the line list.
  3331. * end_ln Specifies the end indext of the line list.
  3332. *
  3333. * Return: True if there is a vertical line as a child of a container.
  3334. * False if there are no vertical lines in the child of a
  3335. * container/cell.
  3336. *
  3337. *****************************************************************************/
  3338. static _DtCvValue
  3339. LinesMayChange(
  3340. _DtCanvasStruct *canvas,
  3341. int start_ln,
  3342. int end_ln,
  3343. int brdr_cnt)
  3344. {
  3345. /*
  3346. * If border count is negative, indicates that one of the lines
  3347. * is for the bottom of the container/cell. Ignore for now.
  3348. * we want to check the lines in the container/cell.
  3349. */
  3350. if (brdr_cnt < 0)
  3351. brdr_cnt = -brdr_cnt;
  3352. /*
  3353. * get rid of the line count for this object,
  3354. * AdjustObjectPosition can take care of it.
  3355. */
  3356. end_ln -= brdr_cnt;
  3357. /*
  3358. * Now check for vertical lines that would
  3359. * be affected by a height change.
  3360. */
  3361. while (start_ln < end_ln)
  3362. {
  3363. if (_DtCvLINE_VERT == canvas->line_lst[start_ln].dir)
  3364. return True;
  3365. start_ln++;
  3366. }
  3367. return False;
  3368. }
  3369. /******************************************************************************
  3370. * Function: ProcessContainer
  3371. *
  3372. * Initializes the display line and graphic tables.
  3373. *****************************************************************************/
  3374. static void
  3375. ProcessContainer(
  3376. _DtCanvasStruct *canvas,
  3377. LayoutInfo *layout,
  3378. _DtCvSegmentI *con_seg,
  3379. _DtCvUnit min_y,
  3380. _DtCvUnit *ret_width,
  3381. _DtCvUnit *ret_max_x,
  3382. int *ret_cnt)
  3383. {
  3384. int getLn;
  3385. const char *saveJustifyChar = layout->info.align_char;
  3386. _DtCvUnit yPad = 0;
  3387. _DtCvUnit xPad = 0;
  3388. _DtCvUnit maxWidth = 0;
  3389. _DtCvUnit maxXPos = 0;
  3390. _DtCvUnit myMinY = -1;
  3391. _DtCvUnit saveLeft = layout->left;
  3392. _DtCvUnit saveRight = layout->right;
  3393. _DtCvUnit saveLead = layout->info.leading;
  3394. _DtCvUnit saveFirst = layout->first;
  3395. _DtCvUnit saveYpos = layout->info.y_pos;
  3396. _DtCvValue saveStatic = layout->stat_flag;
  3397. _DtCvValue saveBrdr = layout->brdr_flag;
  3398. _DtCvFrmtOption saveJustify = layout->txt_justify;
  3399. LayFrmtInfo frmtInfo;
  3400. DataPoint basePt;
  3401. DataPoint curPt;
  3402. /*
  3403. * check to see if this element breaks the formatting sequence.
  3404. * If so save any information in the buffer, reset the margins and
  3405. * add the appropriate lines, and check for going over boundaries.
  3406. */
  3407. if (NotJoining(layout))
  3408. {
  3409. CheckSaveInfo(canvas, layout, con_seg, 0);
  3410. CheckFormat(layout, True);
  3411. }
  3412. /*
  3413. * check to see if this segment is the segment we want as our first
  3414. * visible line.
  3415. */
  3416. CheckId(layout, _DtCvContainerIdOfSeg(con_seg));
  3417. /*
  3418. * Set beginning text and line counts
  3419. */
  3420. frmtInfo = DefLayFrmtInfo;
  3421. SetBeginCounts(canvas, &(frmtInfo.cnt));
  3422. /*
  3423. * Get the first indent and set the current container pointer to me.
  3424. */
  3425. layout->first = _DtCvContainerFMarginOfSeg(con_seg) / layout->divisor;
  3426. layout->left = _DtCvContainerLMarginOfSeg(con_seg) / layout->divisor;
  3427. layout->right = _DtCvContainerRMarginOfSeg(con_seg) / layout->divisor;
  3428. layout->info.leading = _DtCvContainerLeadingOfSeg(con_seg);
  3429. /*
  3430. * check to see if we violate the horiz_pad_hint on the left, right or
  3431. * first margins.
  3432. */
  3433. if (canvas->metrics.horiz_pad_hint > _DtCvContainerLMarginOfSeg(con_seg))
  3434. layout->left = _DtCvContainerLMarginOfSeg(con_seg);
  3435. else if (layout->left < canvas->metrics.horiz_pad_hint)
  3436. layout->left = canvas->metrics.horiz_pad_hint;
  3437. if (canvas->metrics.horiz_pad_hint > _DtCvContainerRMarginOfSeg(con_seg))
  3438. layout->right = _DtCvContainerRMarginOfSeg(con_seg);
  3439. else if (layout->right < canvas->metrics.horiz_pad_hint)
  3440. layout->right = canvas->metrics.horiz_pad_hint;
  3441. if (canvas->metrics.horiz_pad_hint > _DtCvContainerFMarginOfSeg(con_seg))
  3442. layout->first = _DtCvContainerFMarginOfSeg(con_seg);
  3443. else if (layout->first < canvas->metrics.horiz_pad_hint)
  3444. layout->first = canvas->metrics.horiz_pad_hint;
  3445. /*
  3446. * check to see if there is more squeeze room available.
  3447. */
  3448. if (layout->left > canvas->metrics.horiz_pad_hint
  3449. || layout->right > canvas->metrics.horiz_pad_hint
  3450. || layout->first > canvas->metrics.horiz_pad_hint)
  3451. layout->margin_non_zero = True;
  3452. /*
  3453. * set the formatting type for this container
  3454. */
  3455. layout->stat_flag = False;
  3456. if (_DtCvContainerTypeOfSeg(con_seg) == _DtCvLITERAL)
  3457. layout->stat_flag = True;
  3458. /*
  3459. * check to see if this element breaks the formatting sequence.
  3460. * If so, add lines, etc.
  3461. */
  3462. if (NotJoining(layout))
  3463. {
  3464. /*
  3465. * Adjust margins and y position for bordering
  3466. */
  3467. AdjustForBorders (canvas, layout, Border(con_seg), BrdWidth(con_seg),
  3468. &yPad, &xPad);
  3469. _DtCvAddSpace(_DtCvContainerTMarginOfSeg(con_seg),
  3470. &(layout->info.y_pos));
  3471. /*
  3472. * check for flow limits.
  3473. */
  3474. CheckFormat(layout, True);
  3475. /*
  3476. * get the parent's data point in the stack
  3477. * and add the current container's left and right to it.
  3478. */
  3479. GetCurrentDataPoint(layout, &basePt);
  3480. basePt.left += saveLeft;
  3481. basePt.right += saveRight;
  3482. /*
  3483. * if we don't inherit the the text justification
  3484. * set the new value.
  3485. */
  3486. if (_DtCvINHERIT != _DtCvContainerJustifyOfSeg(con_seg))
  3487. {
  3488. layout->txt_justify = _DtCvContainerJustifyOfSeg(con_seg);
  3489. if (_DtCvJUSTIFY_NUM == layout->txt_justify)
  3490. layout->info.align_char = PeriodStr;
  3491. else if (_DtCvJUSTIFY_CHAR == layout->txt_justify)
  3492. {
  3493. layout->info.align_char = _DtCvContainerJustifyCharOfSeg(con_seg);
  3494. /*
  3495. * check to see if the character is 'valid'.
  3496. * if not, default out of JUSTIFY_CHAR
  3497. */
  3498. if (NULL != layout->info.align_char ||
  3499. '\0' == layout->info.align_char)
  3500. layout->txt_justify = _DtCvJUSTIFY_LEFT;
  3501. }
  3502. }
  3503. /*
  3504. * terminate the previous rendering list
  3505. */
  3506. if (NULL != layout->lst_rendered)
  3507. layout->lst_rendered->next_disp = NULL;
  3508. layout->lst_rendered = NULL;
  3509. /*
  3510. * push the data point and reset margin/text info.
  3511. */
  3512. PushDataPoint(layout, &basePt);
  3513. SetMargins(layout);
  3514. SetTextPosition(layout, True);
  3515. }
  3516. /*
  3517. * determine the minimum Y that the child of this container should
  3518. * occupy. To do so, subtract off the bottom border pad and the
  3519. * bottom margin.
  3520. */
  3521. if (0 < min_y)
  3522. {
  3523. myMinY = min_y - yPad;
  3524. if (_DtCvWRAP_JOIN != _DtCvContainerFlowOfSeg(con_seg))
  3525. {
  3526. _DtCvUnit bPad = 0;
  3527. _DtCvAddSpace(_DtCvContainerBMarginOfSeg(con_seg), &bPad);
  3528. myMinY -= bPad;
  3529. }
  3530. }
  3531. /*
  3532. * format the segment
  3533. */
  3534. saveYpos = layout->info.y_pos;
  3535. GetCurrentDataPoint(layout, &curPt);
  3536. /*
  3537. * reset the max x variable
  3538. */
  3539. layout->info.cur_max_x = 0;
  3540. ProcessSegmentList(canvas, layout, _DtCvContainerListOfSeg(con_seg),
  3541. myMinY,
  3542. &maxWidth, &maxXPos, NULL);
  3543. /*
  3544. * if this container forces a wrap join of the next item,
  3545. * save the current line, but don't add space or null the
  3546. * last rendered item.
  3547. */
  3548. CheckSaveInfo(canvas, layout, con_seg, 0);
  3549. if (maxWidth < layout->info.cur_max_x - curPt.left + layout->right)
  3550. maxWidth = layout->info.cur_max_x - curPt.left + layout->right;
  3551. if (maxXPos < layout->info.cur_max_x)
  3552. maxXPos = layout->info.cur_max_x;
  3553. if (_DtCvWRAP_JOIN != _DtCvContainerFlowOfSeg(con_seg))
  3554. {
  3555. /*
  3556. * Save any information in the buffer,
  3557. * reset the margins and add the appropriate lines,
  3558. * and check for going over boundaries.
  3559. */
  3560. _DtCvAddSpace(_DtCvContainerBMarginOfSeg(con_seg),
  3561. &(layout->info.y_pos));
  3562. /*
  3563. * terminate the previous rendering list
  3564. */
  3565. if (NULL != layout->lst_rendered)
  3566. layout->lst_rendered->next_disp = NULL;
  3567. layout->lst_rendered = NULL;
  3568. }
  3569. /*
  3570. * remove this element's data points from the stack.
  3571. */
  3572. RemoveDataPoint(layout, &basePt);
  3573. /*
  3574. * include the bottom border (if needed) in the ending y position
  3575. */
  3576. layout->info.y_pos += yPad;
  3577. /*
  3578. * Set the ending counts for the lines and text in me.
  3579. * This sets the ending counts for the lines contained in me,
  3580. * NOT the lines in my border.
  3581. */
  3582. SetEndCounts(canvas, &(frmtInfo.cnt), 0);
  3583. /*
  3584. * does this object need to be adjust within its height?
  3585. */
  3586. if (0 < min_y && layout->info.y_pos < min_y)
  3587. {
  3588. AdjustObjectPosition(canvas, layout, TxtVertJustify(con_seg),
  3589. frmtInfo.cnt.beg_txt, frmtInfo.cnt.beg_ln,
  3590. frmtInfo.cnt.beg_brk,
  3591. frmtInfo.cnt.end_txt, frmtInfo.cnt.end_ln,
  3592. frmtInfo.cnt.end_brk,
  3593. 0, min_y - layout->info.y_pos - yPad, 0, 0, 0);
  3594. layout->info.y_pos = min_y;
  3595. }
  3596. /*
  3597. * Now draw the borders
  3598. * If borders are drawn, cur_max_x & max_x_pos may get changed
  3599. * if a right side border is drawn.
  3600. */
  3601. if (maxWidth < layout->max_width - curPt.left - curPt.right)
  3602. maxWidth = layout->max_width - curPt.left - curPt.right;
  3603. getLn = DrawBorders (canvas, layout, Border(con_seg),
  3604. BrdData(con_seg), BrdWidth(con_seg),
  3605. saveYpos, layout->info.y_pos - yPad,
  3606. curPt.left,
  3607. curPt.left + maxWidth);
  3608. /*
  3609. * check to see if we need to save the container counts away
  3610. * because we might need to move the entire container as one
  3611. * to honor the boundary. This will occur if the flag to honor
  3612. * a boundary is set to _DtCvUSE_BOUNDARY_MOVE, this container has
  3613. * border lines, the container's parent is not a table nor
  3614. * is the container within another container that has a border.
  3615. */
  3616. if (_DtCvUSE_BOUNDARY_MOVE == canvas->constraint
  3617. && True == layout->brdr_flag
  3618. && False == saveBrdr && False == layout->table_flag)
  3619. {
  3620. GrpInfo *info = (GrpInfo *) malloc (sizeof(GrpInfo));
  3621. /*
  3622. * warning - nothing done if malloc error.
  3623. */
  3624. if (NULL != info)
  3625. {
  3626. /*
  3627. * initialize to the end information of the container.
  3628. */
  3629. info->cnt = frmtInfo.cnt;
  3630. /*
  3631. * take into account the borders for this container
  3632. */
  3633. SetEndCounts(canvas, &(info->cnt), getLn);
  3634. /*
  3635. * set the linked list information
  3636. */
  3637. info->next_info = layout->grp_lst;
  3638. layout->grp_lst = info;
  3639. }
  3640. }
  3641. /*
  3642. * set the return values.
  3643. */
  3644. *ret_max_x = layout->info.cur_max_x;
  3645. *ret_width = maxWidth;
  3646. if (*ret_width < layout->max_width - curPt.left - curPt.right)
  3647. *ret_width = layout->max_width - curPt.left - curPt.right;
  3648. /*
  3649. * Restore the previous information
  3650. */
  3651. layout->left = saveLeft;
  3652. layout->right = saveRight;
  3653. layout->first = saveFirst;
  3654. layout->stat_flag = saveStatic;
  3655. layout->brdr_flag = saveBrdr;
  3656. layout->info.leading = saveLead;
  3657. /*
  3658. * Besides checking for flow constraints, also (re)sets margins and
  3659. * text information.
  3660. */
  3661. CheckFormat(layout, True);
  3662. layout->txt_justify = saveJustify;
  3663. layout->info.align_char = saveJustifyChar;
  3664. /*
  3665. * for tables and such, return how many lines were drawn around this
  3666. * container.
  3667. */
  3668. if (ret_cnt)
  3669. *ret_cnt = getLn;
  3670. return;
  3671. }
  3672. /******************************************************************************
  3673. * Function: ProcessSegmentList
  3674. *
  3675. * Process the segment list, laying it out according to left, right,
  3676. * and first margins specified. Returns the max_width of the all
  3677. * segments processed and the maximum x coordinate used.
  3678. *****************************************************************************/
  3679. static void
  3680. ProcessSegmentList(
  3681. _DtCanvasStruct *canvas,
  3682. LayoutInfo *layout,
  3683. _DtCvSegmentI *cur_seg,
  3684. _DtCvUnit min_y,
  3685. _DtCvUnit *ret_width,
  3686. _DtCvUnit *ret_max_x,
  3687. int **ret_vert)
  3688. {
  3689. int junk;
  3690. int saveTravCnt = canvas->trav_cnt;
  3691. int saveTxtCnt = canvas->txt_cnt;
  3692. int saveLineCnt = canvas->line_cnt;
  3693. int saveBrkCnt = canvas->brk_cnt;
  3694. _DtCvUnit tempX;
  3695. _DtCvUnit tempLen;
  3696. _DtCvUnit width;
  3697. _DtCvUnit nWidth = 0;
  3698. _DtCvUnit leftMargin = 0;
  3699. _DtCvUnit rightMargin = 0;
  3700. _DtCvUnit topHeight = 0;
  3701. _DtCvUnit botHeight = 0;
  3702. _DtCvUnit maxWidth = 0;
  3703. _DtCvUnit saveYpos = layout->info.y_pos;
  3704. _DtCvSegmentI *segStart = cur_seg;
  3705. LayFrmtInfo *headInfo = NULL;
  3706. LayFrmtInfo *lastHead = NULL;
  3707. LayFrmtInfo *nxtHead;
  3708. _DtCvLayoutInfo startInfo;
  3709. _DtCvValue redo = False;
  3710. _DtCvValue joinCleared = False;
  3711. _DtCvValue flag;
  3712. TopDims topBot;
  3713. SideDims sideDims;
  3714. CornerDims cornerDims;
  3715. FlowDims flowDims;
  3716. DataPoint basePt;
  3717. DataPoint leftPt;
  3718. DataPoint rightPt;
  3719. /*
  3720. * clear the controller arrays
  3721. */
  3722. InitDimArrays(&topBot, &sideDims, &cornerDims, &flowDims);
  3723. /*
  3724. * get the current left and right values or 'base'.
  3725. */
  3726. GetCurrentDataPoint(layout, &basePt);
  3727. /*
  3728. * ???
  3729. */
  3730. leftPt = basePt;
  3731. rightPt = basePt;
  3732. leftPt.y_pos = _CEFORMAT_ALL;
  3733. rightPt.y_pos = _CEFORMAT_ALL;
  3734. /*
  3735. * process all the controller type containers in the segment list
  3736. */
  3737. while (NULL != cur_seg)
  3738. {
  3739. if (_DtCvIsSegContainer(cur_seg) && _DtCvIsSegController(cur_seg))
  3740. {
  3741. /*
  3742. * want to clear this once and only once. Then any join
  3743. * directives will survive, though if two or more controllers
  3744. * have the directive set, the 'last' one will win out.
  3745. */
  3746. if (False == joinCleared)
  3747. {
  3748. _DtCvSetJoinInfo(&(layout->info), False, -1);
  3749. joinCleared = True;
  3750. }
  3751. /*
  3752. * process the 'controller'
  3753. */
  3754. nxtHead = ProcessController(canvas, layout, cur_seg);
  3755. /*
  3756. * update the dimension arrays so that the controller
  3757. * will get placed correctly.
  3758. */
  3759. UpdateDimensionArrays(cur_seg, nxtHead->width, nxtHead->height,
  3760. &topBot, &sideDims, &cornerDims, &flowDims,
  3761. &leftMargin, &rightMargin);
  3762. /*
  3763. * remember this controller.
  3764. */
  3765. if (NULL == headInfo)
  3766. headInfo = nxtHead;
  3767. else
  3768. lastHead->next_info = nxtHead;
  3769. lastHead = nxtHead;
  3770. }
  3771. /*
  3772. * go to the next segment
  3773. */
  3774. cur_seg = cur_seg->next_seg;
  3775. }
  3776. /*
  3777. * Now reset the margins based on the controllers found
  3778. */
  3779. if (NULL != headInfo)
  3780. {
  3781. DetermineMaxDims(&topBot, &cornerDims, leftMargin, rightMargin,
  3782. &topHeight, &botHeight, &maxWidth);
  3783. layout->info.y_pos += topHeight;
  3784. layout->left += leftMargin;
  3785. layout->right += rightMargin;
  3786. DetermineFlowConstraints(layout, flowDims,
  3787. basePt.left, basePt.right,
  3788. layout->info.y_pos, &leftPt, &rightPt);
  3789. /*
  3790. * get rid of the leftMargin and rightMargin values in maxWidth
  3791. * otherwise the use of layout->left & layout->right will double
  3792. * the value.
  3793. */
  3794. maxWidth = maxWidth - leftMargin - rightMargin;
  3795. if (layout->max_width < maxWidth + basePt.left + basePt.right +
  3796. layout->left + layout->right)
  3797. layout->max_width = maxWidth + basePt.left + basePt.right +
  3798. layout->left + layout->right;
  3799. SetMargins(layout);
  3800. SetTextPosition(layout, True);
  3801. if (JoinSet(layout))
  3802. {
  3803. int cnt;
  3804. int joinLine = layout->info.join_line;
  3805. int start = canvas->txt_lst[joinLine].byte_index;
  3806. int count = canvas->txt_lst[joinLine].length;
  3807. _DtCvSegmentI *pSeg = canvas->txt_lst[joinLine].seg_ptr;
  3808. _DtCvUnit tmpWidth;
  3809. /*
  3810. * change the starting location of the following text.
  3811. * take into account the left margin that *hasn't*
  3812. * been added to the controlling container.
  3813. */
  3814. layout->info.text_x_pos = canvas->txt_lst[joinLine].text_x
  3815. + layout->lmargin;
  3816. layout->info.cur_len = 0;
  3817. /*
  3818. * now calculate the width of this line.
  3819. */
  3820. while (pSeg != NULL && count > 0)
  3821. {
  3822. _DtCvGetWidthOfSegment(canvas,pSeg,start,count,
  3823. &cnt, &tmpWidth, NULL);
  3824. layout->info.text_x_pos += tmpWidth;
  3825. count -= cnt;
  3826. start = 0;
  3827. pSeg = pSeg->next_disp;
  3828. }
  3829. }
  3830. }
  3831. /*
  3832. * now format for non-controller containers and non-containers.
  3833. * re-start at the beginning.
  3834. */
  3835. cur_seg = segStart;
  3836. /*
  3837. * Save some information incase we have to redo the layout. I.e.
  3838. * we overflow the sizing.
  3839. */
  3840. startInfo = layout->info;
  3841. saveTravCnt = canvas->trav_cnt;
  3842. saveTxtCnt = canvas->txt_cnt;
  3843. saveLineCnt = canvas->line_cnt;
  3844. saveBrkCnt = canvas->brk_cnt;
  3845. while (NULL != cur_seg)
  3846. {
  3847. width = layout->max_width - layout->info.text_x_pos
  3848. - layout->rmargin - layout->info.cur_len;
  3849. /*
  3850. * check to see if this item should start a line.
  3851. */
  3852. CheckSetLineStart(layout, cur_seg);
  3853. /*
  3854. * check to see if this item will cause a page break.
  3855. */
  3856. CheckForPageBreak(canvas, cur_seg, layout->info.y_pos);
  3857. switch (_DtCvPrimaryTypeOfSeg(cur_seg))
  3858. {
  3859. case _DtCvCONTAINER:
  3860. if (!(_DtCvIsSegController(cur_seg)))
  3861. ProcessContainer(canvas, layout, cur_seg, min_y,
  3862. &junk, &junk, &junk);
  3863. break;
  3864. case _DtCvREGION:
  3865. /*
  3866. * flag that this segment needs a line number
  3867. */
  3868. cur_seg->internal_use = (void *) -1;
  3869. /*
  3870. * process the segment
  3871. */
  3872. if (_DtCvIsSegInLine(cur_seg))
  3873. {
  3874. /*
  3875. * if a hypertext link, this will add it to
  3876. * the internal list.
  3877. */
  3878. CheckAddToHyperList(canvas, cur_seg);
  3879. /*
  3880. * get the traversal width
  3881. */
  3882. nWidth = _DtCvGetTraversalWidth(canvas, cur_seg,
  3883. layout->info.lst_hyper);
  3884. /*
  3885. * check to see if this region can end a line
  3886. */
  3887. flag = _DtCvCheckLineSyntax(canvas,cur_seg,0,0,False);
  3888. /*
  3889. * if this can't end a line, get the length up to
  3890. * the next segment that can and base whether to
  3891. * save pased on that.
  3892. */
  3893. tempLen = 0;
  3894. if (False == flag)
  3895. {
  3896. tempLen = _DtCvGetNextWidth(canvas,
  3897. _DtCvSTRING,
  3898. layout->info.lst_hyper,
  3899. cur_seg->next_seg,
  3900. 0, cur_seg, NULL, NULL, NULL);
  3901. /*
  3902. * if the next width is zero, reset the flag.
  3903. */
  3904. if (tempLen <= 0)
  3905. flag = True;
  3906. }
  3907. tempLen += nWidth;
  3908. /*
  3909. * if not joining, but my length goes over the
  3910. * working width, save out the current buffered
  3911. * information
  3912. */
  3913. if (NotJoining(layout) &&
  3914. _DtCvWidthOfRegionSeg(cur_seg) + tempLen > width)
  3915. CheckSaveInfo (canvas, layout, cur_seg, 0);
  3916. /*
  3917. * up counts on the buffered information.
  3918. */
  3919. layout->info.line_bytes += 1;
  3920. layout->info.cur_len +=
  3921. (_DtCvWidthOfRegionSeg(cur_seg) + nWidth);
  3922. /*
  3923. * does the next segment need to join with
  3924. * this one? If so, set the information
  3925. */
  3926. _DtCvSetJoinInfo(&(layout->info), (flag ? 0 : 1), -1);
  3927. if (_DtCvIsSegNewLine(cur_seg))
  3928. SaveInfo(canvas, layout, cur_seg, 0);
  3929. }
  3930. else
  3931. {
  3932. /*
  3933. * clear out the join information
  3934. * standalone figures can't join with others.
  3935. */
  3936. _DtCvSetJoinInfo(&(layout->info), False, -1);
  3937. /*
  3938. * figures are standalone. Save any
  3939. * information in the buffer away.
  3940. */
  3941. CheckSaveInfo (canvas, layout, cur_seg, 0);
  3942. /*
  3943. * check to see if this segment is
  3944. * a hypertext. If so, add it to the
  3945. * list if it hasn't been added yet.
  3946. */
  3947. CheckAddToHyperList(canvas, cur_seg);
  3948. /*
  3949. * get the traversal width, if any.
  3950. */
  3951. nWidth = _DtCvGetTraversalWidth(canvas, cur_seg,
  3952. layout->info.lst_hyper);
  3953. /*
  3954. * now save the standalone figure
  3955. */
  3956. layout->info.line_bytes += 1;
  3957. layout->info.cur_len +=
  3958. _DtCvWidthOfRegionSeg(cur_seg) + nWidth;
  3959. SaveInfo(canvas, layout, cur_seg->next_seg, 0);
  3960. /*
  3961. * check for wrapping overflow
  3962. */
  3963. CheckFormat(layout, False);
  3964. }
  3965. /*
  3966. * indicate this segment as the last item rendered
  3967. */
  3968. if (NULL != layout->lst_rendered)
  3969. layout->lst_rendered->next_disp = cur_seg;
  3970. layout->lst_rendered = cur_seg;
  3971. break;
  3972. case _DtCvLINE:
  3973. /*
  3974. * lines are standalone. Save any
  3975. * information in the buffer away.
  3976. */
  3977. CheckSaveInfo (canvas, layout, cur_seg, 0);
  3978. /*
  3979. * if the line_width is zero, make it 1 so
  3980. * that it really does take some space.
  3981. */
  3982. nWidth = _DtCvWidthOfLineSeg(cur_seg);
  3983. if (0 == nWidth)
  3984. nWidth = 1;
  3985. /*
  3986. * start with it going all the way across the window.
  3987. */
  3988. width = layout->max_width;
  3989. tempX = 0;
  3990. /*
  3991. * or does it only extend across the container?
  3992. */
  3993. if (_DtCvIsSegBlockLine(cur_seg))
  3994. {
  3995. tempX = layout->lmargin;
  3996. width = layout->max_width - tempX - layout->rmargin;
  3997. }
  3998. SaveLine (canvas, layout, _DtCvLINE_HORZ,
  3999. _DtCvDataOfLineSeg(cur_seg), nWidth, tempX,
  4000. layout->info.y_pos, width);
  4001. layout->info.y_pos += nWidth;
  4002. break;
  4003. case _DtCvMARKER:
  4004. /*
  4005. * check to see if marker is the target id
  4006. */
  4007. CheckId(layout, _DtCvIdOfMarkerSeg(cur_seg));
  4008. break;
  4009. case _DtCvNOOP:
  4010. if (_DtCvIsSegNewLine(cur_seg))
  4011. SaveInfo(canvas, layout, cur_seg, 0);
  4012. break;
  4013. case _DtCvSTRING:
  4014. /*
  4015. * flag that this segment needs a line number
  4016. */
  4017. cur_seg->internal_use = (void *) -1;
  4018. /*
  4019. * process the string
  4020. */
  4021. ProcessStringSegment(canvas, layout, cur_seg);
  4022. /*
  4023. * check for wrapping overflow.
  4024. */
  4025. if (_DtCvIsSegNewLine(cur_seg))
  4026. CheckFormat(layout, False);
  4027. /*
  4028. * indicate this segment as the last item rendered
  4029. */
  4030. if (NULL != layout->lst_rendered)
  4031. layout->lst_rendered->next_disp = cur_seg;
  4032. layout->lst_rendered = cur_seg;
  4033. break;
  4034. case _DtCvTABLE:
  4035. ProcessTable(canvas, layout, cur_seg, min_y);
  4036. default:
  4037. break;
  4038. }
  4039. /*
  4040. * get the next segment
  4041. */
  4042. cur_seg = cur_seg->next_seg;
  4043. /*
  4044. * check the flowing text points
  4045. */
  4046. if (leftPt.y_pos > 0 &&
  4047. leftPt.x_units > layout->max_width - leftPt.left - leftPt.right)
  4048. {
  4049. layout->max_width = leftPt.x_units + leftPt.left + leftPt.right;
  4050. redo = True;
  4051. }
  4052. if (rightPt.y_pos > 0 &&
  4053. rightPt.x_units > layout->max_width-rightPt.left-rightPt.right)
  4054. {
  4055. layout->max_width = rightPt.x_units + rightPt.left + rightPt.right;
  4056. redo = True;
  4057. }
  4058. /*
  4059. * have we violated the available space?
  4060. * if so, we'll have to reformat.
  4061. */
  4062. if (redo == True)
  4063. {
  4064. redo = False;
  4065. cur_seg = segStart;
  4066. canvas->trav_cnt = saveTravCnt;
  4067. canvas->txt_cnt = saveTxtCnt;
  4068. canvas->line_cnt = saveLineCnt;
  4069. canvas->brk_cnt = saveBrkCnt;
  4070. layout->info = startInfo;
  4071. if (rightPt.y_pos > 0)
  4072. {
  4073. RemoveDataPoint(layout, &rightPt); /* make sure its gone */
  4074. InsertDataPoint(layout, &rightPt);
  4075. }
  4076. if (leftPt.y_pos > 0)
  4077. {
  4078. RemoveDataPoint(layout, &leftPt); /* make sure its gone */
  4079. InsertDataPoint(layout, &leftPt);
  4080. }
  4081. /*
  4082. * Now reset the margins based on the controllers found
  4083. */
  4084. if (NULL != headInfo)
  4085. {
  4086. layout->left += leftMargin;
  4087. layout->right += rightMargin;
  4088. SetMargins(layout);
  4089. SetTextPosition(layout, True);
  4090. if (JoinSet(layout))
  4091. {
  4092. int cnt;
  4093. int joinLine = layout->info.join_line;
  4094. int start = canvas->txt_lst[joinLine].byte_index;
  4095. int count = canvas->txt_lst[joinLine].length;
  4096. _DtCvSegmentI *pSeg = canvas->txt_lst[joinLine].seg_ptr;
  4097. _DtCvUnit tmpWidth;
  4098. /*
  4099. * change the starting location of the following text.
  4100. * take into account the left margin that *hasn't*
  4101. * been added to the controlling container.
  4102. */
  4103. layout->info.text_x_pos = canvas->txt_lst[joinLine].text_x
  4104. + layout->lmargin;
  4105. layout->info.cur_len = 0;
  4106. /*
  4107. * now calculate the width of this line.
  4108. */
  4109. while (pSeg != NULL && count > 0)
  4110. {
  4111. _DtCvGetWidthOfSegment(canvas,pSeg,start,count,
  4112. &cnt, &tmpWidth, NULL);
  4113. layout->info.text_x_pos += tmpWidth;
  4114. count -= cnt;
  4115. start = 0;
  4116. pSeg = pSeg->next_disp;
  4117. }
  4118. }
  4119. }
  4120. }
  4121. }
  4122. RemoveDataPoint(layout, &leftPt);
  4123. RemoveDataPoint(layout, &rightPt);
  4124. /*
  4125. * if there were heads, now place them correctly.
  4126. */
  4127. if (NULL != headInfo)
  4128. {
  4129. _DtCvUnit blockHeight;
  4130. _DtCvUnit blockWidth;
  4131. /*
  4132. * make sure all of the information in the body is saved out
  4133. */
  4134. CheckSaveInfo (canvas, layout, NULL, 0);
  4135. /*
  4136. * now calculate the non-controllers overall height.
  4137. */
  4138. blockHeight = layout->info.y_pos - saveYpos - topHeight;
  4139. /*
  4140. * now figure the head positions.
  4141. */
  4142. DetermineHeadPositioning(&topBot, &sideDims, &cornerDims, &flowDims,
  4143. saveYpos, topHeight,
  4144. blockHeight, &blockHeight);
  4145. /*
  4146. * if the maximum available space was exceeded by the text
  4147. * calculate a new max width
  4148. */
  4149. if (layout->max_width < layout->info.cur_max_x + layout->right)
  4150. layout->max_width = layout->info.cur_max_x + layout->right;
  4151. blockWidth = layout->max_width - basePt.left - basePt.right
  4152. - layout->left - layout->right;
  4153. nxtHead = headInfo;
  4154. cur_seg = segStart;
  4155. while (cur_seg != NULL)
  4156. {
  4157. if (_DtCvIsSegContainer(cur_seg) && _DtCvIsSegController(cur_seg))
  4158. {
  4159. AdjustHeadPosition(canvas, layout, cur_seg,
  4160. &topBot, &sideDims, &cornerDims, &flowDims, nxtHead,
  4161. 0, basePt.left + layout->left - leftMargin, blockWidth,
  4162. leftMargin, rightMargin);
  4163. /*
  4164. * go to the next head element
  4165. */
  4166. nxtHead = nxtHead->next_info;
  4167. /*
  4168. * free the information.
  4169. */
  4170. free(headInfo);
  4171. headInfo = nxtHead;
  4172. }
  4173. /*
  4174. * got to the next segment
  4175. */
  4176. cur_seg = cur_seg->next_seg;
  4177. }
  4178. if (layout->info.y_pos < saveYpos + topHeight + blockHeight)
  4179. layout->info.y_pos = saveYpos + topHeight + blockHeight;
  4180. layout->info.y_pos += botHeight;
  4181. }
  4182. /*
  4183. * set the return values
  4184. */
  4185. *ret_width = layout->info.cur_max_x - basePt.left + layout->right;
  4186. *ret_max_x = layout->info.cur_max_x;
  4187. return;
  4188. }
  4189. /*****************************************************************************
  4190. * Function: static _DtCvUnit MaxOfGroup (
  4191. *
  4192. * Purpose: Determine the maximum of a group.
  4193. *****************************************************************************/
  4194. static void
  4195. MaxOfGroup (
  4196. GrpInfo *group,
  4197. _DtCvDspLine *text,
  4198. _DtCvLineSeg *lines,
  4199. _DtCvUnit max_x,
  4200. _DtCvUnit max_y)
  4201. {
  4202. int i;
  4203. /*
  4204. * initialize
  4205. */
  4206. group->min_x = max_x;
  4207. group->max_x = 0;
  4208. group->top_y = max_y;
  4209. group->bot_y = 0;
  4210. /*
  4211. * find the maximum of the group
  4212. */
  4213. for (i = group->cnt.beg_txt; i < group->cnt.end_txt; i++)
  4214. {
  4215. /*
  4216. * check for min's and max's
  4217. */
  4218. if (group->min_x > text[i].text_x)
  4219. group->min_x = text[i].text_x;
  4220. if (group->max_x < text[i].max_x)
  4221. group->max_x = text[i].max_x;
  4222. if (group->top_y > text[i].baseline - text[i].ascent)
  4223. group->top_y = text[i].baseline - text[i].ascent;
  4224. if (group->bot_y < text[i].baseline + text[i].descent)
  4225. group->bot_y = text[i].baseline + text[i].descent;
  4226. /*
  4227. * indicate that this line has been processed already
  4228. */
  4229. _DtCvSetProcessed(text[i]);
  4230. }
  4231. for (i = group->cnt.beg_ln; i < group->cnt.end_ln; i++)
  4232. {
  4233. /*
  4234. * check for min's and max's
  4235. */
  4236. if (group->min_x > lines[i].pos_x)
  4237. group->min_x = lines[i].pos_x;
  4238. if (group->max_x < lines[i].max_x)
  4239. group->max_x = lines[i].max_x;
  4240. if (group->top_y > lines[i].pos_y)
  4241. group->top_y = lines[i].pos_y;
  4242. if (group->bot_y < lines[i].max_y)
  4243. group->bot_y = lines[i].max_y;
  4244. /*
  4245. * indicate that this line has been processed already
  4246. */
  4247. _DtCvSetProcessed(lines[i]);
  4248. }
  4249. }
  4250. /*****************************************************************************
  4251. * Function: static _DtCvUnit TestSpacing (
  4252. *
  4253. * Parameters:
  4254. *
  4255. * Returns: True if the object is before (x wise) the test object.
  4256. * False if the object is not before (x wise) the text object.
  4257. *
  4258. * Purpose:
  4259. *
  4260. *****************************************************************************/
  4261. static _DtCvStatus
  4262. TestSpacing (
  4263. _DtCvUnit tst_top,
  4264. _DtCvUnit tst_bot,
  4265. _DtCvUnit tst_min,
  4266. _DtCvUnit obj_top,
  4267. _DtCvUnit obj_bot,
  4268. _DtCvUnit obj_max,
  4269. _DtCvUnit needed,
  4270. _DtCvUnit min_space,
  4271. _DtCvUnit *ret_amount)
  4272. {
  4273. _DtCvStatus result = False;
  4274. /*
  4275. * check to see if the object is to the left of the test object
  4276. * to move and that it 'infringes' on the vertical
  4277. * space of the test object.
  4278. *
  4279. * I.e. ----obj_top------
  4280. * | | ----tst_top----
  4281. * ----obj_bot------ | |
  4282. * ----tst_bot----
  4283. *
  4284. * I.e. ----tst_top----
  4285. * ----obj_top------- | |
  4286. * | | ----tst_bot----
  4287. * ----obj_bot-------
  4288. *
  4289. * I.e. ----obj_top------
  4290. * | | ----tst_top----
  4291. * | | | |
  4292. * | | ----tst_bot----
  4293. * ----obj_bot------
  4294. *
  4295. * I.e. ----tst_top----
  4296. * ----obj_top------- | |
  4297. * | | | |
  4298. * ----obj_bot------- | |
  4299. * ----tst_bot----
  4300. */
  4301. if (obj_max < tst_min
  4302. && True == _DtCvCheckInfringement(tst_top, tst_bot, obj_top, obj_bot)
  4303. && needed > tst_min - obj_max)
  4304. {
  4305. /*
  4306. * okay, this infringes on the object's space.
  4307. * truncate the amount of room there is to move the object
  4308. */
  4309. result = True;
  4310. needed = tst_min - obj_max;
  4311. /*
  4312. * is the space between these two objects already squeezed
  4313. * below the minimum allowed?
  4314. */
  4315. if (needed < min_space)
  4316. needed = 0;
  4317. else /* leave the minimum space between the objects */
  4318. needed -= min_space;
  4319. }
  4320. *ret_amount = needed;
  4321. return result;
  4322. }
  4323. /*****************************************************************************
  4324. * Function: static void MoveLeft (
  4325. *
  4326. * Parameters:
  4327. *
  4328. * Returns:
  4329. *
  4330. * Purpose: Moves the object's rules/lines and text lines to the left.
  4331. *
  4332. *****************************************************************************/
  4333. static void
  4334. MoveLeft (
  4335. _DtCanvasStruct *canvas,
  4336. int beg_txt,
  4337. int end_txt,
  4338. int beg_ln,
  4339. int end_ln,
  4340. _DtCvUnit space)
  4341. {
  4342. int i;
  4343. /*
  4344. * bail now if nothing to do.
  4345. */
  4346. if (1 > space)
  4347. return;
  4348. /*
  4349. * move each text/region line.
  4350. */
  4351. for (i = beg_txt; i < end_txt; i++)
  4352. {
  4353. canvas->txt_lst[i].text_x -= space;
  4354. canvas->txt_lst[i].max_x -= space;
  4355. }
  4356. /*
  4357. * move each line/rule.
  4358. */
  4359. for (i = beg_ln; i < end_ln; i++)
  4360. {
  4361. canvas->line_lst[i].pos_x -= space;
  4362. canvas->line_lst[i].max_x -= space;
  4363. }
  4364. }
  4365. /*****************************************************************************
  4366. * Function: static _DtCvUnit CheckSpacing (
  4367. *
  4368. * Purpose: Check the spacing before an object and move any objects
  4369. * before it to the left to make room.
  4370. *
  4371. *****************************************************************************/
  4372. static _DtCvUnit
  4373. CheckSpacing (
  4374. _DtCanvasStruct *canvas,
  4375. LayoutInfo *layout,
  4376. GrpInfo *tst_grp,
  4377. int txt_idx,
  4378. int line_idx,
  4379. _DtCvUnit top_y,
  4380. _DtCvUnit bot_y,
  4381. _DtCvUnit min_x,
  4382. _DtCvUnit needed)
  4383. {
  4384. int i;
  4385. _DtCvUnit space;
  4386. _DtCvUnit maxSpace;
  4387. _DtCvUnit topY;
  4388. _DtCvUnit botY;
  4389. GrpInfo *nxtGrp = layout->grp_lst;
  4390. /*
  4391. * truncate if the amount needed is more than available.
  4392. */
  4393. if (min_x < needed)
  4394. needed = min_x;
  4395. maxSpace = needed;
  4396. /*
  4397. * see what group is before this group and how much space there is
  4398. */
  4399. while (NULL != nxtGrp)
  4400. {
  4401. /*
  4402. * as long as I'm not comparing against myself, try it.
  4403. */
  4404. if (nxtGrp != tst_grp)
  4405. {
  4406. /*
  4407. * is this group before(x wise) the test group, infringing
  4408. * upon the test group's top and bottom positioning (y)
  4409. * and is the amount of space (x wise) between them smaller
  4410. * than the current smallest space found?
  4411. */
  4412. if (True == TestSpacing (top_y, bot_y, min_x,
  4413. nxtGrp->top_y, nxtGrp->bot_y,
  4414. nxtGrp->max_x, needed,
  4415. canvas->metrics.horiz_pad_hint,
  4416. &space))
  4417. {
  4418. space += MoveGroup(canvas, layout, nxtGrp, needed - space);
  4419. if (maxSpace > space)
  4420. maxSpace = space;
  4421. }
  4422. }
  4423. /*
  4424. * check the next group
  4425. */
  4426. nxtGrp = nxtGrp->next_info;
  4427. }
  4428. /*
  4429. * look at each of the text lines;
  4430. */
  4431. for (i = 0; i < canvas->txt_cnt; i++)
  4432. {
  4433. /*
  4434. * Only look at those lines not already processed.
  4435. */
  4436. if (i != txt_idx && _DtCvIsNotProcessed(canvas->txt_lst[i]))
  4437. {
  4438. topY = canvas->txt_lst[i].baseline - canvas->txt_lst[i].ascent;
  4439. botY = canvas->txt_lst[i].baseline - canvas->txt_lst[i].descent;
  4440. if (True == TestSpacing(top_y, bot_y, min_x, topY, botY,
  4441. canvas->txt_lst[i].max_x, needed,
  4442. canvas->metrics.horiz_pad_hint, &space))
  4443. {
  4444. space += MoveText(canvas, layout, i, topY, botY, needed-space);
  4445. if (maxSpace > space)
  4446. maxSpace = space;
  4447. }
  4448. }
  4449. }
  4450. /*
  4451. * look at each of the rules/lines;
  4452. */
  4453. for (i = 0; i < canvas->line_cnt; i++)
  4454. {
  4455. /*
  4456. * Only look at those lines not already processed.
  4457. */
  4458. if (i != line_idx && _DtCvIsNotProcessed(canvas->line_lst[i]))
  4459. {
  4460. /*
  4461. * calculate the top and bottom of the line
  4462. */
  4463. topY = canvas->line_lst[i].pos_y;
  4464. botY = canvas->line_lst[i].max_y;
  4465. if (True == TestSpacing(top_y, bot_y, min_x, topY, botY,
  4466. canvas->line_lst[i].max_x, needed,
  4467. canvas->metrics.horiz_pad_hint, &space))
  4468. {
  4469. space += MoveLines(canvas, layout, i, topY, botY, needed-space);
  4470. if (maxSpace > space)
  4471. maxSpace = space;
  4472. }
  4473. }
  4474. }
  4475. return maxSpace;
  4476. }
  4477. /*****************************************************************************
  4478. * Function: static _DtCvUnit MoveGroup (_DtCanvasStruct canvas);
  4479. *
  4480. * Purpose: To move groupings (container, tables, etc.) as a group to
  4481. * honor boundaries.
  4482. *
  4483. *****************************************************************************/
  4484. static _DtCvUnit
  4485. MoveGroup (
  4486. _DtCanvasStruct *canvas,
  4487. LayoutInfo *layout,
  4488. GrpInfo *tst_grp,
  4489. _DtCvUnit needed)
  4490. {
  4491. _DtCvUnit space;
  4492. /*
  4493. * find out what's in front of it. And how much 'extra' room
  4494. * there is.
  4495. */
  4496. space = CheckSpacing(canvas, layout, tst_grp, -1, -1,
  4497. tst_grp->top_y, tst_grp->bot_y, tst_grp->min_x,
  4498. needed);
  4499. /*
  4500. * now move the group
  4501. */
  4502. MoveLeft(canvas, tst_grp->cnt.beg_txt, tst_grp->cnt.end_txt,
  4503. tst_grp->cnt.beg_ln, tst_grp->cnt.end_ln, space);
  4504. tst_grp->max_x -= space;
  4505. tst_grp->min_x -= space;
  4506. return space;
  4507. }
  4508. /*****************************************************************************
  4509. * Function: static _DtCvUnit MoveText (_DtCanvasStruct canvas);
  4510. *
  4511. * Purpose: To move text lines to honor boundaries.
  4512. *
  4513. *****************************************************************************/
  4514. static _DtCvUnit
  4515. MoveText (
  4516. _DtCanvasStruct *canvas,
  4517. LayoutInfo *layout,
  4518. int idx,
  4519. _DtCvUnit top_y,
  4520. _DtCvUnit bot_y,
  4521. _DtCvUnit needed)
  4522. {
  4523. _DtCvUnit space;
  4524. /*
  4525. * find out what's in front of it. And how much 'extra' room
  4526. * there is.
  4527. */
  4528. space = CheckSpacing(canvas, layout, NULL, idx, -1,
  4529. top_y, bot_y,
  4530. canvas->txt_lst[idx].text_x,
  4531. needed);
  4532. /*
  4533. * now move the group
  4534. */
  4535. MoveLeft(canvas, idx, idx, -1, -1, space);
  4536. return space;
  4537. }
  4538. /*****************************************************************************
  4539. * Function: static _DtCvUnit MoveLines (_DtCanvasStruct canvas);
  4540. *
  4541. * Purpose: To move groupings (container, tables, etc.) as a group to
  4542. * honor boundaries.
  4543. *
  4544. *****************************************************************************/
  4545. static _DtCvUnit
  4546. MoveLines (
  4547. _DtCanvasStruct *canvas,
  4548. LayoutInfo *layout,
  4549. int idx,
  4550. _DtCvUnit top_y,
  4551. _DtCvUnit bot_y,
  4552. _DtCvUnit needed)
  4553. {
  4554. _DtCvUnit space;
  4555. /*
  4556. * find out what's in front of it. And how much 'extra' room
  4557. * there is.
  4558. */
  4559. space = CheckSpacing(canvas, layout, NULL, -1, idx,
  4560. top_y, bot_y,
  4561. canvas->line_lst[idx].pos_x,
  4562. needed);
  4563. /*
  4564. * now move the group
  4565. */
  4566. MoveLeft(canvas, -1, -1, idx, idx, space);
  4567. return space;
  4568. }
  4569. /*****************************************************************************
  4570. * Function: static void CheckMoveInfo (_DtCanvasStruct canvas);
  4571. *
  4572. * Purpose: To move each of the groupings, rules and text lines to
  4573. * honor boundaries.
  4574. *
  4575. *****************************************************************************/
  4576. static void
  4577. CheckMoveInfo (
  4578. _DtCanvasStruct *canvas,
  4579. LayoutInfo *layout)
  4580. {
  4581. int i;
  4582. _DtCvUnit topY;
  4583. _DtCvUnit botY;
  4584. _DtCvUnit maxWidth = canvas->metrics.width;
  4585. GrpInfo *nxtGrp;
  4586. /*
  4587. * fill in the max x of each group
  4588. */
  4589. for (nxtGrp = layout->grp_lst; NULL != nxtGrp; nxtGrp = nxtGrp->next_info)
  4590. {
  4591. /*
  4592. * find the maximum of the group
  4593. */
  4594. MaxOfGroup(nxtGrp, canvas->txt_lst, canvas->line_lst,
  4595. layout->info.max_x_pos, layout->info.y_pos);
  4596. }
  4597. /*
  4598. * now check each group for exceeding the boundary.
  4599. */
  4600. for (nxtGrp = layout->grp_lst; NULL != nxtGrp; nxtGrp = nxtGrp->next_info)
  4601. {
  4602. /*
  4603. * does this group exceed the boundary?
  4604. */
  4605. if (maxWidth < nxtGrp->max_x)
  4606. (void) MoveGroup(canvas, layout, nxtGrp, nxtGrp->max_x - maxWidth);
  4607. }
  4608. /*
  4609. * look at each of the text lines;
  4610. */
  4611. for (i = 0; i < canvas->txt_cnt; i++)
  4612. {
  4613. /*
  4614. * Only look at those lines not already processed.
  4615. */
  4616. if (_DtCvIsNotProcessed(canvas->txt_lst[i]) &&
  4617. maxWidth < canvas->txt_lst[i].max_x)
  4618. {
  4619. topY = canvas->txt_lst[i].baseline - canvas->txt_lst[i].ascent;
  4620. botY = canvas->txt_lst[i].baseline - canvas->txt_lst[i].descent;
  4621. (void) MoveText(canvas, layout, i, topY, botY,
  4622. canvas->txt_lst[i].max_x - maxWidth);
  4623. }
  4624. }
  4625. /*
  4626. * look at each of the rules/lines;
  4627. */
  4628. for (i = 0; i < canvas->line_cnt; i++)
  4629. {
  4630. /*
  4631. * Only look at those lines not already processed.
  4632. */
  4633. if (_DtCvIsNotProcessed(canvas->line_lst[i]) &&
  4634. maxWidth < canvas->line_lst[i].max_x)
  4635. {
  4636. /*
  4637. * calculate the top and bottom of the line
  4638. */
  4639. topY = canvas->line_lst[i].pos_y;
  4640. botY = canvas->line_lst[i].max_y;
  4641. (void) MoveLines(canvas, layout, i, topY, botY,
  4642. canvas->line_lst[i].max_x - maxWidth);
  4643. }
  4644. }
  4645. }
  4646. /*****************************************************************************
  4647. * Function: static void CompareUnits ()
  4648. *
  4649. * Parameters:
  4650. *
  4651. * Returns:
  4652. *
  4653. * Purpose:
  4654. *
  4655. *****************************************************************************/
  4656. static int
  4657. CompareUnits (
  4658. const void *a,
  4659. const void *b)
  4660. {
  4661. _DtCvUnit *aPtr = (_DtCvUnit *) a;
  4662. _DtCvUnit *bPtr = (_DtCvUnit *) b;
  4663. if (*aPtr < *bPtr) return -1;
  4664. if (*aPtr == *bPtr) return 0;
  4665. return 1;
  4666. }
  4667. /*****************************************************************************
  4668. * Function: static void CompareSearchs ()
  4669. *
  4670. * Parameters:
  4671. *
  4672. * Returns:
  4673. *
  4674. * Purpose:
  4675. *
  4676. *****************************************************************************/
  4677. static int
  4678. CompareSearchs (
  4679. const void *a,
  4680. const void *b)
  4681. {
  4682. _DtCvSearchData *searchA = (_DtCvSearchData *) a;
  4683. _DtCvSearchData *searchB = (_DtCvSearchData *) b;
  4684. _DtCvDspLine *lineA = &(searchA->lst[searchA->idx]);
  4685. _DtCvDspLine *lineB = &(searchB->lst[searchB->idx]);
  4686. _DtCvUnit topA = lineA->baseline - lineA->ascent;
  4687. _DtCvUnit topB = lineB->baseline - lineB->ascent;
  4688. _DtCvUnit heightA = lineA->ascent + lineA->descent;
  4689. _DtCvUnit heightB = lineB->ascent + lineB->descent;
  4690. _DtCvUnit centA = topA + (heightA >> 1);
  4691. _DtCvUnit centB = topB + (heightB >> 1);
  4692. if (lineA->baseline + lineA->descent < centB && centA < topB)
  4693. return -1;
  4694. if (lineB->baseline + lineB->descent < centA && centB < topA)
  4695. return 1;
  4696. if (lineA->text_x != lineB->text_x)
  4697. return ((lineA->text_x < lineB->text_x) ? -1 : 1);
  4698. if (topA != topB)
  4699. return ((topA < topB) ? -1 : 1);
  4700. if (heightA != heightB)
  4701. return ((heightA < heightB) ? -1 : 1);
  4702. if (lineA->max_x != lineB->max_x)
  4703. return ((lineA->max_x < lineB->max_x) ? -1 : 1);
  4704. return 0;
  4705. }
  4706. /*****************************************************************************
  4707. * Function: static Status LayoutCanvasInfo (_DtCvHandle canvas);
  4708. *
  4709. * Parameters:
  4710. *
  4711. * Returns:
  4712. *
  4713. * Purpose:
  4714. *
  4715. *****************************************************************************/
  4716. static _DtCvStatus
  4717. LayoutCanvasInfo (
  4718. _DtCanvasStruct *canvas,
  4719. LayoutInfo *layout,
  4720. _DtCvUnit divisor,
  4721. char *target_id)
  4722. {
  4723. int i = 0;
  4724. DataPoint basePt;
  4725. _DtCvUnit maxWidth = 0;
  4726. _DtCvUnit maxXPos = 0;
  4727. _DtCvStatus result = _DtCvSTATUS_OK;
  4728. *layout = DefInfo;
  4729. layout->divisor = divisor;
  4730. layout->max_width = canvas->metrics.width;
  4731. layout->left = canvas->metrics.side_margin;
  4732. layout->right = canvas->metrics.side_margin;
  4733. layout->target_id = target_id;
  4734. _DtCvInitLayoutInfo(canvas, &(layout->info));
  4735. basePt = DefDataPt;
  4736. PushDataPoint(layout, &basePt);
  4737. SetMargins (layout);
  4738. SetTextPosition (layout, True);
  4739. ProcessSegmentList(canvas, layout, canvas->element_lst, -1,
  4740. &maxWidth, &maxXPos, NULL);
  4741. RemoveDataPoint(layout, &basePt);
  4742. /*
  4743. * fill in the max_x of each line of text/regions.
  4744. */
  4745. for (i = 0; i < canvas->txt_cnt; i++)
  4746. canvas->txt_lst[i].max_x = MaxXOfLine(canvas, &(canvas->txt_lst[i]));
  4747. /*
  4748. * calculate the actual right hand side boundary.
  4749. */
  4750. layout->info.max_x_pos += canvas->metrics.side_margin;
  4751. /*
  4752. * the max_x_pos so far has indicated where the *next* character,
  4753. * line or region will be *started*. Therefore back up one to
  4754. * indicate the true last position used.
  4755. */
  4756. layout->info.max_x_pos--;
  4757. return result;
  4758. } /* End LayoutCanvasInfo */
  4759. /*****************************************************************************
  4760. * Function: static Status LayoutCanvas (_DtCvHandle canvas);
  4761. *
  4762. * Parameters:
  4763. *
  4764. * Returns:
  4765. *
  4766. * Purpose:
  4767. *
  4768. *****************************************************************************/
  4769. static _DtCvStatus
  4770. LayoutCanvas (
  4771. _DtCanvasStruct *canvas,
  4772. LayoutInfo *layout,
  4773. char *target_id)
  4774. {
  4775. _DtCvUnit divisor = 1;
  4776. _DtCvValue redo;
  4777. _DtCvStatus result;
  4778. int i, search_cnt = canvas->search_cnt;
  4779. do {
  4780. redo = False;
  4781. result = LayoutCanvasInfo(canvas, layout, divisor, target_id);
  4782. /*
  4783. * Are we suppose to honor the boundary?
  4784. * If so, do any lines go over the boundary?
  4785. * Is there any margins that can be decremented?
  4786. */
  4787. if (_DtCvSTATUS_OK == result
  4788. && (_DtCvUSE_BOUNDARY == canvas->constraint ||
  4789. _DtCvUSE_BOUNDARY_MOVE == canvas->constraint)
  4790. && layout->info.max_x_pos >= canvas->metrics.width)
  4791. {
  4792. if (_DtCvUSE_BOUNDARY_MOVE == canvas->constraint)
  4793. {
  4794. int i;
  4795. /*
  4796. * clear the processed flag from all the text/region lines.
  4797. */
  4798. for (i = 0; i < canvas->txt_cnt; i++)
  4799. _DtCvClearProcessed(canvas->txt_lst[i]);
  4800. /*
  4801. * clear the processed flag from all the line/rules.
  4802. */
  4803. for (i = 0; i < canvas->line_cnt; i++)
  4804. _DtCvClearProcessed(canvas->line_lst[i]);
  4805. CheckMoveInfo(canvas, layout);
  4806. /*
  4807. * recalculate the new max x
  4808. */
  4809. layout->info.max_x_pos = 0;
  4810. for (i = 0; i < canvas->txt_cnt; i++)
  4811. if (layout->info.max_x_pos < canvas->txt_lst[i].max_x)
  4812. layout->info.max_x_pos = canvas->txt_lst[i].max_x;
  4813. for (i = 0; i < canvas->line_cnt; i++)
  4814. if (layout->info.max_x_pos < canvas->line_lst[i].max_x)
  4815. layout->info.max_x_pos = canvas->line_lst[i].max_x;
  4816. layout->info.max_x_pos--;
  4817. }
  4818. else if (True == layout->margin_non_zero)
  4819. {
  4820. redo = True;
  4821. divisor *= 2;
  4822. canvas->txt_cnt = 0;
  4823. canvas->line_cnt = 0;
  4824. canvas->trav_cnt = 0;
  4825. }
  4826. }
  4827. } while (True == redo);
  4828. /*
  4829. * clean up table information
  4830. */
  4831. if (NULL != layout->grp_lst)
  4832. free(layout->grp_lst);
  4833. /*
  4834. * subtract one from the y position to indicate the *last*
  4835. * pixel/column/etc that will be rendered.
  4836. */
  4837. canvas->max_y = layout->info.y_pos - 1;
  4838. canvas->max_x = layout->info.max_x_pos;
  4839. for (i = search_cnt; i < canvas->search_cnt; i++)
  4840. {
  4841. canvas->searchs[i - search_cnt] = canvas->searchs[i];
  4842. canvas->searchs[i - search_cnt].lst = canvas->txt_lst;
  4843. }
  4844. canvas->search_cnt -= search_cnt;
  4845. /*
  4846. * are there any search hits?
  4847. */
  4848. if (0 != canvas->search_cnt)
  4849. qsort (canvas->searchs, canvas->search_cnt, sizeof(_DtCvSearchData),
  4850. CompareSearchs);
  4851. /*
  4852. * sort the page break list.
  4853. */
  4854. if (0 != canvas->brk_cnt)
  4855. qsort (canvas->pg_breaks, canvas->brk_cnt, sizeof(_DtCvUnit),
  4856. CompareUnits);
  4857. return result;
  4858. } /* End LayoutCanvas */
  4859. /*****************************************************************************
  4860. * Function: static void SortTraversal (_DtCvHandle canvas);
  4861. *
  4862. * Parameters:
  4863. *
  4864. * Returns:
  4865. *
  4866. * Purpose:
  4867. *
  4868. *****************************************************************************/
  4869. static void
  4870. SortTraversal (_DtCanvasStruct *canvas)
  4871. {
  4872. int i;
  4873. /*
  4874. * sort the links correctly. First, establish the x,y,width,height
  4875. * of each link.
  4876. */
  4877. for (i = 0; i < canvas->trav_cnt; i++)
  4878. {
  4879. if (_DtCvTraversalLink == canvas->trav_lst[i].type)
  4880. GetLinkInfo(canvas, i, &(canvas->trav_lst[i].x_pos),
  4881. &(canvas->trav_lst[i].y_pos),
  4882. &(canvas->trav_lst[i].width),
  4883. &(canvas->trav_lst[i].height));
  4884. else
  4885. _DtCvCalcMarkPos(canvas, canvas->trav_lst[i].idx,
  4886. &(canvas->trav_lst[i].x_pos),
  4887. &(canvas->trav_lst[i].y_pos),
  4888. &(canvas->trav_lst[i].width),
  4889. &(canvas->trav_lst[i].height));
  4890. }
  4891. _DtCvSortTraversalList(canvas, _DtCvFALSE);
  4892. }
  4893. /*****************************************************************************
  4894. * Function: static void ProcessMarks (_DtCanvasStruct *canvas);
  4895. *
  4896. * Parameters:
  4897. *
  4898. * Returns:
  4899. *
  4900. * Purpose:
  4901. *
  4902. *****************************************************************************/
  4903. static _DtCvStatus
  4904. ProcessMarks (
  4905. _DtCanvasStruct *canvas,
  4906. _DtCvPointInfo **mark_lst)
  4907. {
  4908. int markIdx;
  4909. int result = _DtCvSTATUS_OK;
  4910. _DtCvSelectData beg;
  4911. _DtCvSelectData end;
  4912. _DtCvSegmentI *firstSeg;
  4913. while (NULL != mark_lst && NULL != *mark_lst)
  4914. {
  4915. /*
  4916. * convert the segments to begin and end points
  4917. */
  4918. if (_DtCvSTATUS_BAD == _DtCvCvtSegsToPts(canvas, (*mark_lst)->segs,
  4919. &beg, &end, NULL, NULL, &firstSeg))
  4920. /*
  4921. * just set a return value since this indicates bad data
  4922. * and not system failure.
  4923. */
  4924. result = _DtCvSTATUS_BAD;
  4925. /*
  4926. * now add it to the mark list
  4927. */
  4928. else
  4929. {
  4930. markIdx = _DtCvAddToMarkList(canvas, (*mark_lst)->client_data,
  4931. _DtCvFALSE, &beg, &end);
  4932. /*
  4933. * now put the mark in the traversal list, but don't sort
  4934. * or fill out position and dimension information.
  4935. * SortTraversal() will do that.
  4936. *
  4937. * bail here if system failure indicated.
  4938. */
  4939. if (-1 == markIdx || 0 != _DtCvSetTravEntryInfo(canvas,
  4940. _DtCvGetNextTravEntry(canvas),
  4941. _DtCvTraversalMark, firstSeg,
  4942. markIdx, _DtCvTRUE))
  4943. return _DtCvSTATUS_BAD;
  4944. }
  4945. mark_lst++;
  4946. }
  4947. return result;
  4948. }
  4949. /*****************************************************************************
  4950. * Public Functions
  4951. *****************************************************************************/
  4952. /*****************************************************************************
  4953. * Function: void _DtCanvasResize (_DtCvHandle canvas);
  4954. *
  4955. * Parameters:
  4956. *
  4957. * Returns:
  4958. *
  4959. * Purpose:
  4960. *
  4961. *****************************************************************************/
  4962. _DtCvStatus
  4963. _DtCanvasResize (
  4964. _DtCvHandle canvas_handle,
  4965. _DtCvValue force,
  4966. _DtCvUnit *ret_width,
  4967. _DtCvUnit *ret_height )
  4968. {
  4969. int i;
  4970. _DtCvStatus selectStatus;
  4971. _DtCvStatus retStatus = _DtCvSTATUS_NONE;
  4972. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  4973. _DtCvUnit oldWidth = canvas->metrics.width;
  4974. LayoutInfo layOut;
  4975. _DtCvPointInfo selPt;
  4976. _DtCvPointInfo **markInfo;
  4977. selPt.client_data = NULL;
  4978. selPt.segs = NULL;
  4979. /*
  4980. * check to see if the width has changed - if not,
  4981. * don't do anything (but re-initialize the metrics
  4982. * to get the new height).
  4983. */
  4984. (*(canvas->virt_functions.get_metrics))(canvas->client_data,
  4985. _DtCvCANVAS_TYPE, &(canvas->metrics));
  4986. if (canvas->metrics.width != oldWidth || _DtCvTRUE == force)
  4987. {
  4988. /*
  4989. * remember the current selection.
  4990. */
  4991. selectStatus = _DtCanvasGetSelectionPoints(canvas, &(selPt.segs),
  4992. NULL, NULL);
  4993. /*
  4994. * remember the marks
  4995. */
  4996. if (_DtCvSTATUS_BAD == _DtCvGetMarkSegs(canvas, &markInfo))
  4997. return _DtCvSTATUS_BAD;
  4998. /*
  4999. * Re-Layout the information.
  5000. * First step - invalidate some counters.
  5001. */
  5002. canvas->trav_cnt = 0; /* zero this only because we re-process */
  5003. /* do not zero cur_hyper or we'll loose */
  5004. /* where we are in the TOC */
  5005. canvas->txt_cnt = 0;
  5006. canvas->line_cnt = 0;
  5007. canvas->mark_cnt = 0;
  5008. canvas->brk_cnt = 0;
  5009. /*
  5010. * Layout the information if there is anything to do
  5011. */
  5012. if (_DtCvSTATUS_BAD == LayoutCanvas (canvas, &layOut, NULL))
  5013. return _DtCvSTATUS_BAD;
  5014. /*
  5015. * restore the current selection.
  5016. */
  5017. if (_DtCvSTATUS_OK == selectStatus)
  5018. {
  5019. _DtCanvasActivatePts(canvas,_DtCvACTIVATE_SELECTION, &selPt,
  5020. NULL,NULL);
  5021. _DtCvFreeArray((void **) selPt.segs);
  5022. }
  5023. /*
  5024. * now place the marks in the mark and traversal lists
  5025. */
  5026. ProcessMarks(canvas, markInfo);
  5027. if (NULL != markInfo)
  5028. {
  5029. for (i = 0; NULL != markInfo[i]; i++)
  5030. _DtCvFreeArray((void **) (markInfo[i]->segs));
  5031. _DtCvFreeArray((void **) markInfo);
  5032. }
  5033. /*
  5034. * sort the traversal list.
  5035. */
  5036. SortTraversal(canvas);
  5037. retStatus = _DtCvSTATUS_OK;
  5038. }
  5039. /*
  5040. * return the maximum height and width used
  5041. */
  5042. if (ret_width != NULL)
  5043. *ret_width = canvas->max_x;
  5044. if (ret_height != NULL)
  5045. *ret_height = canvas->max_y;
  5046. return retStatus;
  5047. } /* End _DtCanvasResize */
  5048. /*****************************************************************************
  5049. * Function: void _DtCanvasSetTopic (_DtCvHandle canvas);
  5050. *
  5051. * Parameters:
  5052. *
  5053. * Returns:
  5054. *
  5055. * Purpose:
  5056. *
  5057. *****************************************************************************/
  5058. _DtCvStatus
  5059. _DtCanvasSetTopic (
  5060. _DtCvHandle canvas_handle,
  5061. _DtCvTopicPtr topic,
  5062. _DtCvValue honor_size,
  5063. _DtCvUnit *ret_width,
  5064. _DtCvUnit *ret_height,
  5065. _DtCvUnit *ret_y )
  5066. {
  5067. _DtCvStatus result = _DtCvSTATUS_OK;
  5068. _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle;
  5069. LayoutInfo layOut;
  5070. /*
  5071. * clean the canvas
  5072. */
  5073. _DtCanvasClean (canvas_handle);
  5074. /*
  5075. * attach to the canvas
  5076. */
  5077. canvas->element_lst = topic->seg_list;
  5078. /*
  5079. * Attach the link information
  5080. */
  5081. canvas->link_data = topic->link_data;
  5082. /*
  5083. * init the internal use pointer in all containers to NULL
  5084. */
  5085. _DtCvClearInternalUse(canvas->element_lst, _DtCvFALSE);
  5086. /*
  5087. * Layout the information if there is anything to do
  5088. */
  5089. canvas->constraint = honor_size;
  5090. if (_DtCvSTATUS_BAD == LayoutCanvas (canvas, &layOut, topic->id_str))
  5091. return _DtCvSTATUS_BAD;
  5092. /*
  5093. * add the marks to the mark and traversal lists
  5094. */
  5095. ProcessMarks(canvas, topic->mark_list);
  5096. /*
  5097. * sort the traversal list.
  5098. */
  5099. SortTraversal(canvas);
  5100. /*
  5101. * return the maximum height and width used
  5102. * And the location of the id.
  5103. */
  5104. if (ret_width != NULL)
  5105. *ret_width = canvas->max_x;
  5106. if (ret_height != NULL)
  5107. *ret_height = canvas->max_y;
  5108. if (ret_y != NULL)
  5109. {
  5110. if (NULL != layOut.target_id && True != layOut.id_found)
  5111. result = _DtCvSTATUS_ID_BAD;
  5112. *ret_y = layOut.id_Ypos;
  5113. }
  5114. return result;
  5115. } /* End _DtCanvasSetTopic */