123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390 |
- /*
- * Copyright 2021
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * These are the four essential freedoms with GNU GPL software:
- * 1: freedom to run the program, for any purpose
- * 2: freedom to study how the program works, and change it to make it do what you wish
- * 3: freedom to redistribute copies to help your Free Software friends
- * 4: freedom to distribute copies of your modified versions to your Free Software friends
- * , ,
- * / \
- * ((__-^^-,-^^-__))
- * `-_---' `---_-'
- * `--|o` 'o|--'
- * \ ` /
- * ): :(
- * :o_o:
- * "-"
- *
- * SPDX-License-Identifier: GPL-3.0+
- * License-Filename: LICENSE
- */
- #ifdef __cplusplus
- #error "you are clowns said Linus"
- #endif
- #ifdef WIN32
- #error "Sorry, install GNU / Linux GPL Free software see fsf.org or debian.org"
- #endif
- /*
- * The layout theory is described in this book
- * Graph Drawing And Applications For Software And Knowledge Engineers
- * ISBN10 9810248792 or ISBN13 9789810248796
- * Kozo Sugiyama, World Scientific Publishing Co Pte Ltd
- * K. Sugiyama, S. Tagawa and M. Toda, "Methods for Visual Understanding of
- * Hierarchical Systems". IEEE Transactions on Systems, Man and Cybernetics
- * 11(2):109-125, 1981.
- */
- #include "config.h"
- /* for a qt5 gui it is only needed to create a main.cpp instead of using main.c and link the rest of the code
- * or rewrite for nappgui because that is also good and does not add extra overhead
- * and nappgui can be compiled for linux gtk-3, windos and mac os-x
- * some parts of nappgui are c++ and that is not c
- */
- /* needed to get basename() from string.h
- * #define _GNU_SOURCE
- * basename() changed in g_path_get_basename()
- */
- /* needed to get M_PI definition from math.h
- * #define _GNU_SOURCE
- * replaced with #define M_PI below after math.h
- */
- /* needed to get the proto for strdup() in string.h
- * now strdup changed into calloc() and strcpy()
- * #define _POSIX_C_SOURCE 200809L
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <math.h>
- #include <zlib.h>
- #ifdef HAVE_UNISTD_H
- #include <unistd.h> /* should have sync() */
- #endif
- /* math.h should have set this */
- #ifndef M_PI
- #define M_PI 3.141592
- #endif
- #include <gtk/gtk.h>
- #include <gdk/gdkkeysyms.h>
- #include <cairo.h>
- #include <cairo-svg.h>
- /* this should be the way check for glib version */
- #if GLIB_CHECK_VERSION (2,30,0)
- #ifdef WIN32
- #else
- #include <glib-unix.h>
- #endif
- #endif
- /* check for gtk versions */
- #if GTK_CHECK_VERSION (4,0,0)
- #elif GTK_CHECK_VERSION (3,0,0)
- #elif GTK_CHECK_VERSION (3,2,0)
- #elif GTK_CHECK_VERSION (3,4,0)
- #elif GTK_CHECK_VERSION (3,6,0)
- #elif GTK_CHECK_VERSION (3,8,0)
- #elif GTK_CHECK_VERSION (3,12,0)
- #elif GTK_CHECK_VERSION (3,14,0)
- #elif GTK_CHECK_VERSION (2,0,0)
- #elif GTK_CHECK_VERSION (1,0,0)
- #else
- /* assume gtk-2 */
- #endif
- #include "splay-tree.h"
- #include "main.h"
- #include "hier.h"
- #include "uniqnode.h"
- #include "uniqstr.h"
- #include "uniqgraph.h"
- #include "bubbling.h"
- #include "sugi.h"
- #include "pos.h"
- #include "posz.h"
- #include "gml_scanner.h"
- #include "gml_parser.h"
- #include "dpif.h"
- #include "dot.tab.h"
- #include "vcg.h"
- #include "jgf.h"
- #include "bgv.h"
- #include "dpmem.h"
- /* todo the pango font routines can be improved */
- /*
- * a GTK font pattern. These have the syntax
- * fontname [properties] [fontsize]
- *
- * where fontname is the family name,
- * properties is a list of property values separated by spaces,
- * and fontsize is the point size.
- * The properties that you may specify for GTK font patterns are as follows:
- * Slant properties: ‘Italic’ or ‘Oblique’. If omitted, the default (roman) slant is implied.
- * Weight properties: ‘Bold’, ‘Book’, ‘Light’, ‘Medium’, ‘Semi-bold’, or ‘Ultra-light’. If omitted, ‘Medium’ weight is implied.
- * Width properties: ‘Semi-Condensed’ or ‘Condensed’. If omitted, a default width is used.
- * Here are some examples of GTK font patterns:
- * Monospace 12
- * Monospace Bold Italic 12
- */
- #if 0 /* this does not work yet for windows, todo */
- #ifdef WIN32
- /* pango on wine has issues with font options, so use only a font name */
- /* name of font to use, example "Sans" */
- #define DEFAULT_FONTNAME "sans"
- /* name of slant to use, example "Italic", "Oblique" or "Roman" */
- #define DEFAULT_FONTSLANT " "
- /* name of weight to use, example "Bold", "Book", "Light", "Medium", "Semi-bold", "Ultra-light" */
- #define DEFAULT_FONTWEIGHT " "
- /* name of condensed to use, example "Semi-Condensed", "Condensed" */
- #define DEFAULT_FONTCONDENSED " "
- /* font size to use, example "10", "18", "20" etc. */
- #define DEFAULT_FONTSIZE "14"
- #define DEFAULT_FONTSIZE_INT 14
- #endif
- #endif
- /* Linux defaults */
- /* name of font to use, example "Sans" */
- #define DEFAULT_FONTNAME "sans"
- /* name of slant to use, example "Italic", "Oblique" or "Roman" */
- #define DEFAULT_FONTSLANT "roman"
- /* name of weight to use, example "Bold", "Book", "Light", "Medium", "Semi-bold", "Ultra-light" */
- #define DEFAULT_FONTWEIGHT "light"
- /* name of condensed to use, example "Semi-Condensed", "Condensed" */
- #define DEFAULT_FONTCONDENSED "condensed"
- /* font size to use, example "10", "18", "20" etc. */
- #define DEFAULT_FONTSIZE "12"
- #define DEFAULT_FONTSIZE_INT 12
- /* edge line thickness double value for example 0.5, 1.0, 1.5 */
- #define DEFAULT_EDGE_THICKNESS 1.0
- /* pixels in padding for gtk_box_pack try values 0, 1, 5, 20 */
- #define PACKPADDING 0
- /* window initial (x,y) size in pixels */
- #define TOP_LEVEL_WINDOW_XSIZE 800
- #define TOP_LEVEL_WINDOW_YSIZE 650
- /* probed once to check if pango lib support markup overline="single" attribute */
- static int pango_overline = -1;
- /* last open/save dir */
- static char *lastopendir = NULL;
- static char *lastsavedir = NULL;
- /* main argv[0] */
- static char *argv0 = NULL;
- /* debug output to stdout */
- static int option_gdebug = 0; /* 0,1,2 */
- /* draw edgelines as soft splines */
- static int option_splines = 1;
- /* exposed size of draw area */
- static int drawing_area_xsize = 0;
- static int drawing_area_ysize = 0;
- /* set if there is data to draw */
- static int validdata = 0;
- /* r/g/b of drawing alt color "grey82" */
- static int altr = 0xd1;
- static int altg = 0xd1;
- static int altb = 0xd1;
- /* zoom scaling factor changed by zoom slider */
- static double zfactor = 1.0;
- /* x offset changed by x slider */
- static int vxmin = 0;
- /* y offset changed by y slider */
- static int vymin = 0;
- /* top level window also used in maingtk2.c */
- static GtkWidget *mainwindow1 = (GtkWidget *) 0;
- /* where to draw */
- static GtkWidget *drawingarea1 = (GtkWidget *) 0;
- /* popup level window also used in maingtk2.c */
- static GtkWidget *popupwindow1 = (GtkWidget *) 0;
- /* position mode button */
- static GtkWidget *posbutton = (GtkWidget *) 0;
- /* edge labels */
- static GtkWidget *elabel1 = (GtkWidget *) 0;
- /* status line gtk buffers */
- static GtkTextBuffer *entry1buffer = NULL;
- static char charentry1buffer[80];
- /* old mouse (x,y) left button clicked used for dragging drawing */
- static int mouse_oldx = 0;
- static int mouse_oldy = 0;
- /* if set, draw dummy nodes */
- static int option_drawdummy = 0;
- /* gtk-0 can be re-compiled as mini-gtk also for freedos */
- #if (GTK_HAVE_API_VERSION_0 == 1)
- #warning "gtk-0 not implemented"
- #endif
- /* gtk-1 re-compile failed and looks to have 64bits issues */
- #if (GTK_HAVE_API_VERSION_1 == 1)
- #warning "gtk-1 not implemented"
- #endif
- /* sliders */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- static GtkObject *adjvscale1 = NULL; /* left vertical zoom slider */
- static GtkObject *adjvscale2 = NULL;
- static GtkObject *adjhscale1 = NULL;
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- static GtkAdjustment *adjvscale1 = NULL; /* left vertical zoom slider */
- static GtkAdjustment *adjvscale2 = NULL;
- static GtkAdjustment *adjhscale1 = NULL;
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- static GtkAdjustment *adjvscale1 = NULL; /* left vertical zoom slider */
- static GtkAdjustment *adjvscale2 = NULL;
- static GtkAdjustment *adjhscale1 = NULL;
- #endif
- /* forward decl. */
- static void do_clear_all(int mode);
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- static void top_level_window_main_quit(void);
- static void on_top_level_window_open1_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_open2_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_open3_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_open4_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_open5_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_svg1_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_dia1_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_jgf1_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_quit1_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_fullscreen1_activate(GtkMenuItem * menuitem, gpointer user_data);
- static void on_top_level_window_unfullscreen1_activate(GtkMenuItem * menuitem, gpointer user_data);
- #ifdef WIN32
- /* product activation for windows */
- static void on_top_level_window_activate1_activate(GtkMenuItem * menuitem, gpointer user_data);
- #endif
- #endif
- static void xspin_changed(GtkWidget * widget, gpointer spinbutton);
- static void yspin_changed(GtkWidget * widget, gpointer spinbutton);
- static void pos_changed(GtkWidget * widget, gpointer spinbutton);
- static void bary_changed(GtkWidget * widget, gpointer spinbutton);
- static void rank_changed(GtkWidget * widget, gpointer spinbutton);
- static void check1_toggle(GtkWidget * widget, gpointer window);
- static void dummy1_toggle(GtkWidget * widget, gpointer window);
- static void elabel1_toggle(GtkWidget * widget, gpointer window);
- static void label1_toggle(GtkWidget * widget, gpointer window);
- static void nnames1_toggle(GtkWidget * widget, gpointer window);
- static void popup1_toggle(GtkWidget * widget, gpointer window);
- static void mirrory1_toggle(GtkWidget * widget, gpointer window);
- static void on_top_level_window_drawingarea1_expose_event_edges(cairo_t * crp);
- static void on_top_level_window_drawingarea1_expose_event_nodes_record_r(cairo_t * crp, struct gml_node
- *node, struct gml_rl
- *info);
- static void on_top_level_window_drawingarea1_expose_event_nodes_record(cairo_t * crp, struct gml_node
- *node);
- static void on_top_level_window_drawingarea1_expose_event_nodes_html(cairo_t * crp, struct gml_node
- *node);
- static void on_top_level_window_drawingarea1_expose_event_nodes(cairo_t * crp);
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- static void show_about(GtkWidget * widget, gpointer data);
- #endif
- /* show about with ok button */
- static void show_about_bare(void);
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* left slider */
- static void on_vscale1_changed(GtkAdjustment * adj);
- /* right slider */
- static void on_vscale2_changed(GtkAdjustment * adj);
- /* bottom slider */
- static void on_hscale1_changed(GtkAdjustment * adj);
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* left slider */
- static void on_vscale1_changed(GtkAdjustment * adj, gpointer data);
- /* right slider */
- static void on_vscale2_changed(GtkAdjustment * adj, gpointer data);
- /* bottom slider */
- static void on_hscale1_changed(GtkAdjustment * adj, gpointer data);
- #endif
- #if GTK_HAVE_API_VERSION_2 == 1
- /* redraw drawing area */
- static gboolean on_top_level_window_drawingarea1_expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer user_data);
- #endif
- #if GTK_HAVE_API_VERSION_3 == 1
- /* redraw drawing area */
- static gboolean on_top_level_window_drawingarea1_draw_event(GtkWidget * widget, cairo_t * crdraw, gpointer user_data);
- #endif
- #if GTK_HAVE_API_VERSION_2 == 1
- /* redraw drawing area */
- static gboolean popuparea1_expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer user_data);
- #endif
- #if GTK_HAVE_API_VERSION_3 == 1
- /* redraw drawing area */
- static gboolean popuparea1_draw_event(GtkWidget * widget, cairo_t * crdraw, gpointer user_data);
- #endif
- /* fit drawing in window */
- static void dofit(void);
- static void do_layout_all(struct gml_graph *g);
- static void do_relayout_all(struct gml_graph *g);
- static void finalxy(struct gml_graph *g);
- static struct gml_p *static_maingtk_textsizes1sz(struct gml_rl *info);
- static void static_maingtk_textsizes1rl(struct gml_rl *info);
- static void static_maingtk_textsizes1eq(struct gml_rl *info);
- static void static_maingtk_textsizes2rl(struct gml_rl *info, int count, int xoff, int yoff, int bbx, int bby);
- static void static_maingtk_textsizes1n(struct gml_node *node);
- static void static_maingtk_textsizes(void);
- static void update_status_text(char *text);
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- static gboolean on_mouse_clicked(GtkWidget * widget, GdkEventButton * event, gpointer user_data);
- static gboolean on_motion_notify_event(GtkWidget * widget, GdkEventMotion * event);
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- static void on_motion_notify_event(GtkEventControllerMotion * controller, double x, double y, GtkWidget * widget);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- static void sliders_default(void)
- {
- zfactor = 1.0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale1), 50);
- vxmin = 0;
- vymin = 0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), 0);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), 0);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- static void sliders_default(void)
- {
- zfactor = 1.0;
- vxmin = 0;
- vymin = 0;
- return;
- }
- #endif
- static int initialfiles(int argc, char *argv[])
- {
- char *s = NULL;
- char *fnam = NULL;
- gzFile fgv = (gzFile) 0;
- gzFile fgml = (gzFile) 0;
- gzFile fvcg = (gzFile) 0;
- /* check for optinal gml file on commandline
- * on commandline file.gml.gz is supported
- * but not dot.gz or vcg.gz
- */
- if (argc > 1) {
- fnam = argv[1];
- if ((*fnam) != '-') {
- /* find the last '.'
- * if (strcmp(s, ".gz") == 0)
- * then it is gzipped, but need to know the part before
- */
- s = strrchr(fnam, '.');
- if (s) {
- /*
- * switch between dot or gml or vcg parser
- * gcc generates vcg file with file extention .ci
- */
- if ((strcmp(s, ".vcg") == 0) || (strcmp(s, ".ci") == 0)) {
- /* assume this is a gcc vcg file */
- fvcg = gzopen(fnam, "r");
- if (fvcg) {
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 2;
- /* create root graph */
- create_maingraph();
- /* parse the data */
- if (vcgparse(maingraph, fvcg, fnam, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- printf("%s\n", parsermessage);
- fflush(stdout);
- gzclose(fvcg);
- /* data is invalid at this point */
- validdata = 0;
- } else {
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- while (gtk_events_pending()) {
- gtk_main_iteration();
- /* this updates the status text */
- }
- #endif
- do_layout_all(maingraph);
- /* update status text */
- update_status_text(NULL);
- /* set sliders to defaults */
- sliders_default();
- drawing_area_xsize = TOP_LEVEL_WINDOW_XSIZE;
- drawing_area_ysize = TOP_LEVEL_WINDOW_YSIZE;
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- }
- gzclose(fvcg);
- } else {
- printf("%s(): cannot open `%s' file for reading\n", __func__, fnam);
- fflush(stdout);
- }
- /* end of vcg file at start */
- } else if ((strcmp(s, ".dot") == 0) || (strcmp(s, ".gv") == 0)) {
- /* assume this is a dot file */
- fgv = gzopen(fnam, "r");
- if (fgv) {
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 1;
- /* create root graph */
- create_maingraph();
- /* parse the data */
- if (dotparse(maingraph, fgv, fnam, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- printf("%s\n", parsermessage);
- fflush(stdout);
- gzclose(fgv);
- /* data is invalid at this point */
- validdata = 0;
- } else {
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- while (gtk_events_pending()) {
- gtk_main_iteration();
- /* this updates the status text */
- }
- #endif
- do_layout_all(maingraph);
- /* update status text */
- update_status_text(NULL);
- /* set sliders to defaults */
- sliders_default();
- drawing_area_xsize = TOP_LEVEL_WINDOW_XSIZE;
- drawing_area_ysize = TOP_LEVEL_WINDOW_YSIZE;
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- }
- gzclose(fgv);
- } else {
- printf("%s(): cannot open `%s' file for reading\n", __func__, fnam);
- fflush(stdout);
- }
- /* end of dot file at start */
- } else {
- /* assume gml file */
- fgml = gzopen(fnam, "r");
- if (fgml) {
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 0;
- /* create root graph */
- create_maingraph();
- /* parse the gml data */
- if (gmlparse(maingraph, fgml, fnam, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- printf("%s\n", parsermessage);
- fflush(stdout);
- gzclose(fgml);
- /* data is invalid at this point */
- validdata = 0;
- } else {
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- while (gtk_events_pending()) {
- gtk_main_iteration();
- /* this updates the status text */
- }
- #endif
- do_layout_all(maingraph);
- /* update status text */
- update_status_text(NULL);
- /* set sliders to defaults */
- sliders_default();
- drawing_area_xsize = TOP_LEVEL_WINDOW_XSIZE;
- drawing_area_ysize = TOP_LEVEL_WINDOW_YSIZE;
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- }
- gzclose(fgml);
- } else {
- printf("%s(): cannot open `%s' file for reading\n", __func__, fnam);
- fflush(stdout);
- }
- /* end of gml file at start */
- }
- }
- }
- }
- return (0);
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- static void set_current_folder(GtkFileChooser * chooser, const char *name);
- static void fullscreen_changed(GSimpleAction * action, GVariant * value, gpointer win);
- static void on_top_level_window_quit1_activate(GSimpleAction * action, GVariant * paramter, gpointer user_data);
- /* open dot decl. */
- static void open1_activated(GSimpleAction * action, GVariant * parameter, gpointer app);
- /* open gml */
- static void open2_activated(GSimpleAction * action, GVariant * parameter, gpointer app);
- /* open vcg */
- static void open3_activated(GSimpleAction * action, GVariant * parameter, gpointer app);
- /* open jgf */
- static void open4_activated(GSimpleAction * action, GVariant * parameter, gpointer app);
- /* open bgv */
- static void open5_activated(GSimpleAction * action, GVariant * parameter, gpointer app);
- /* save svg */
- static void save1_activated(GSimpleAction * action, GVariant * parameter, gpointer app);
- /* save dia xml */
- static void save2_activated(GSimpleAction * action, GVariant * parameter, gpointer app);
- /* save json jgf data */
- static void save3_activated(GSimpleAction * action, GVariant * parameter, gpointer app);
- /* show about box with gtk lib info */
- static void about_activated(GSimpleAction * action, GVariant * parameter, gpointer app)
- {
- if (action) {
- }
- if (parameter) {
- }
- if (app) {
- }
- show_about_bare();
- return;
- }
- /* draw on screen */
- static void draw_function_for_gtk4(GtkDrawingArea * area, cairo_t * cr, int width, int height, gpointer user_data);
- /* draw on pupup window */
- static void popuparea1_draw_event_for_gtk4(GtkDrawingArea * area, cairo_t * crdraw, int width, int height, gpointer user_data);
- /* start the gtk-4 gui
- * this gui is manual crafted and does not depend on builder software or external files
- * then it should be more sure long term maintance is possible
- * it can be manual extended and is easier then expected
- */
- static int maingtk4_activate(GApplication * app, gpointer * user_data)
- {
- GtkWidget *vbox1 = NULL;
- GtkWidget *hbox1 = NULL;
- GtkWidget *vbox2 = NULL;
- GtkWidget *hbox2 = NULL;
- GtkWidget *vscale1 = NULL;
- GtkWidget *vscale2 = NULL;
- GtkWidget *hscale1 = NULL;
- GtkWidget *vbox3 = NULL;
- GtkWidget *hbox3 = NULL;
- GtkWidget *xspinlabel = NULL;
- GtkWidget *xspinbutton = NULL;
- GtkWidget *yspinlabel = NULL;
- GtkWidget *yspinbutton = NULL;
- GtkWidget *pos1 = NULL;
- /* GtkWidget *posbutton is global */
- GtkWidget *check1 = NULL;
- GtkWidget *dummy1 = NULL;
- GtkWidget *entry1 = NULL;
- GtkWidget *vbox4 = NULL;
- GtkWidget *hbox4 = NULL;
- GtkWidget *rank1 = NULL;
- GtkWidget *rankbutton = NULL;
- GtkWidget *barylabel = NULL;
- GtkWidget *barybutton = NULL;
- /* GtkWidget *elabel1 = NULL; is global */
- GtkWidget *label1 = NULL;
- GtkWidget *nnames1 = NULL;
- GtkWidget *popup1 = NULL;
- GtkWidget *mirrory1 = NULL;
- GtkEventController *controller = NULL;
- if (user_data) {
- }
- /* create main window */
- mainwindow1 = gtk_application_window_new(GTK_APPLICATION(app));
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* pre-set some size */
- gtk_window_set_default_size(GTK_WINDOW(mainwindow1), TOP_LEVEL_WINDOW_XSIZE, TOP_LEVEL_WINDOW_YSIZE);
- GSimpleAction *act_open1 = g_simple_action_new("open1", NULL);
- GSimpleAction *act_open2 = g_simple_action_new("open2", NULL);
- GSimpleAction *act_open3 = g_simple_action_new("open3", NULL);
- GSimpleAction *act_open4 = g_simple_action_new("open4", NULL);
- GSimpleAction *act_open5 = g_simple_action_new("open5", NULL);
- GSimpleAction *act_save1 = g_simple_action_new("save1", NULL);
- GSimpleAction *act_save2 = g_simple_action_new("save2", NULL);
- GSimpleAction *act_save3 = g_simple_action_new("save3", NULL);
- GSimpleAction *act_about = g_simple_action_new("about", NULL);
- GSimpleAction *act_fullscreen = g_simple_action_new_stateful("fullscreen", NULL, g_variant_new_boolean(FALSE));
- GSimpleAction *act_quit = g_simple_action_new("quit", NULL);
- GMenu *menubar = g_menu_new();
- GMenu *menu = g_menu_new();
- GMenu *section1 = g_menu_new();
- GMenuItem *menu_item_opendot = g_menu_item_new("Open dot", "win.open1");
- GMenuItem *menu_item_opengml = g_menu_item_new("Open gml", "win.open2");
- GMenuItem *menu_item_openvcg = g_menu_item_new("Open ci", "win.open3");
- GMenuItem *menu_item_openjgf = g_menu_item_new("Open jgf", "win.open4");
- GMenuItem *menu_item_openbgv = g_menu_item_new("Open bgv", "win.open5");
- GMenuItem *menu_item_savesvg = g_menu_item_new("Save svg", "win.save1");
- GMenuItem *menu_item_savedia = g_menu_item_new("Save dia", "win.save2");
- GMenuItem *menu_item_savejgf = g_menu_item_new("Save jgf", "win.save3");
- GMenuItem *menu_item_about = g_menu_item_new("About", "win.about");
- GMenuItem *menu_item_fullscreen = g_menu_item_new("Full Screen", "win.fullscreen");
- GMenuItem *menu_item_quit = g_menu_item_new("Quit", "app.quit");
- g_signal_connect(act_fullscreen, "change-state", G_CALLBACK(fullscreen_changed), mainwindow1);
- g_signal_connect(act_open1, "activate", G_CALLBACK(open1_activated), app); /* open dot */
- g_signal_connect(act_open2, "activate", G_CALLBACK(open2_activated), app); /* open gml */
- g_signal_connect(act_open3, "activate", G_CALLBACK(open3_activated), app); /* open vcg */
- g_signal_connect(act_open4, "activate", G_CALLBACK(open4_activated), app); /* open jgf */
- g_signal_connect(act_open5, "activate", G_CALLBACK(open5_activated), app); /* open bgv */
- g_signal_connect(act_save1, "activate", G_CALLBACK(save1_activated), app); /* save svg */
- g_signal_connect(act_save2, "activate", G_CALLBACK(save2_activated), app); /* save dia xml */
- g_signal_connect(act_save3, "activate", G_CALLBACK(save3_activated), app); /* save json jgf data */
- g_signal_connect(act_about, "activate", G_CALLBACK(about_activated), app);
- g_signal_connect(act_quit, "activate", G_CALLBACK(on_top_level_window_quit1_activate), app);
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_open1)); /* open dot */
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_open2)); /* open gml */
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_open3)); /* open vcg */
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_open4)); /* open jgf */
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_open5)); /* open bgv */
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_save1)); /* save svg */
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_save2)); /* save dia xml */
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_save3)); /* save json jgf data */
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_about));
- g_action_map_add_action(G_ACTION_MAP(mainwindow1), G_ACTION(act_fullscreen));
- g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(act_quit));
- /* open graph data */
- g_menu_append_item(section1, menu_item_opendot);
- g_menu_append_item(section1, menu_item_opengml);
- g_menu_append_item(section1, menu_item_openvcg);
- g_menu_append_item(section1, menu_item_openjgf);
- g_menu_append_item(section1, menu_item_openbgv);
- /* save drawing */
- g_menu_append_item(section1, menu_item_savesvg);
- g_menu_append_item(section1, menu_item_savedia);
- g_menu_append_item(section1, menu_item_savejgf);
- /* others */
- g_menu_append_item(section1, menu_item_about);
- g_menu_append_item(section1, menu_item_fullscreen);
- g_menu_append_item(section1, menu_item_quit);
- g_object_unref(menu_item_about);
- g_object_unref(menu_item_fullscreen);
- g_object_unref(menu_item_savesvg);
- g_object_unref(menu_item_savedia);
- g_object_unref(menu_item_savejgf);
- g_object_unref(menu_item_opendot);
- g_object_unref(menu_item_opengml);
- g_object_unref(menu_item_openvcg);
- g_object_unref(menu_item_openjgf);
- g_object_unref(menu_item_openbgv);
- g_object_unref(menu_item_quit);
- g_menu_append_section(menu, NULL, G_MENU_MODEL(section1));
- g_menu_append_submenu(menubar, "File", G_MENU_MODEL(menu));
- gtk_application_set_menubar(GTK_APPLICATION(app), G_MENU_MODEL(menubar));
- gtk_application_window_set_show_menubar(GTK_APPLICATION_WINDOW(mainwindow1), TRUE);
- /* next vertical area for slider and drawing are */
- vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, /* spacing */ 0);
- gtk_widget_set_vexpand(vbox1, TRUE);
- gtk_window_set_child(GTK_WINDOW(mainwindow1), vbox1);
- hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, /* spacing */ 0);
- gtk_widget_set_hexpand(hbox1, TRUE);
- gtk_box_append(GTK_BOX(vbox1), hbox1);
- /*
- * in hbox1
- * left zoom slider
- * drawing area
- * right y slider
- * below x slider
- */
- /* add next area to the vbox1 */
- /* vertical slider in hbox1 for the zoom factor 50% is 1:1 */
- adjvscale1 = gtk_adjustment_new(50, 0, 100, 0, 0, 0);
- vscale1 = gtk_scale_new(GTK_ORIENTATION_VERTICAL, adjvscale1);
- /* stretch slider vertical */
- gtk_widget_set_vexpand(vscale1, TRUE);
- /* slider routine */
- g_signal_connect(G_OBJECT(adjvscale1), "value-changed", G_CALLBACK(on_vscale1_changed), NULL);
- gtk_box_append(GTK_BOX(hbox1), vscale1);
- /* where to draw in hbox1 */
- drawingarea1 = gtk_drawing_area_new();
- /* stretch maximal */
- gtk_widget_set_vexpand(drawingarea1, TRUE);
- gtk_widget_set_hexpand(drawingarea1, TRUE);
- /* add routines for drawing */
- gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(drawingarea1), draw_function_for_gtk4, NULL, NULL);
- gtk_box_append(GTK_BOX(hbox1), drawingarea1);
- /* add motion routine in the drawingarea */
- controller = gtk_event_controller_motion_new();
- g_signal_connect(G_OBJECT(controller), "motion", G_CALLBACK(on_motion_notify_event), NULL);
- gtk_widget_add_controller(GTK_WIDGET(drawingarea1), controller);
- /* at right vertical slider in hbox1 for the y position range 0...100% of full image size */
- adjvscale2 = gtk_adjustment_new(0, 0, 100, 0, 0, 0);
- vscale2 = gtk_scale_new(GTK_ORIENTATION_VERTICAL, adjvscale2);
- /* stretch slider vertical */
- gtk_widget_set_vexpand(vscale2, TRUE);
- /* add slider */
- g_signal_connect(G_OBJECT(adjvscale2), "value-changed", G_CALLBACK(on_vscale2_changed), NULL);
- gtk_box_append(GTK_BOX(hbox1), vscale2);
- /* next vertical area for horizontal slider */
- vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, /* spacing */ 0);
- gtk_widget_set_vexpand(vbox2, FALSE);
- gtk_box_append(GTK_BOX(vbox1), vbox2);
- hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, /* spacing */ 0);
- gtk_widget_set_hexpand(hbox2, TRUE);
- gtk_box_append(GTK_BOX(vbox2), hbox2);
- /* add horizontal slider */
- /* horizontal scroller 0..100% of drawing size */
- adjhscale1 = gtk_adjustment_new(0, 0, 100, 0, 0, 0);
- hscale1 = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, adjhscale1);
- /* stretch slider */
- gtk_widget_set_hexpand(hscale1, TRUE);
- /* slider routine */
- g_signal_connect(G_OBJECT(adjhscale1), "value-changed", G_CALLBACK(on_hscale1_changed), NULL);
- gtk_box_append(GTK_BOX(hbox2), hscale1);
- /* next vertical area for options */
- vbox3 = gtk_box_new(GTK_ORIENTATION_VERTICAL, /* spacing */ 0);
- gtk_widget_set_vexpand(vbox3, FALSE);
- gtk_box_append(GTK_BOX(vbox2), vbox3);
- hbox3 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, /* spacing */ 0);
- gtk_widget_set_hexpand(hbox3, TRUE);
- gtk_box_append(GTK_BOX(vbox3), hbox3);
- /* add the options below the horizontal slider */
- /* stretch drawing in x dir */
- xspinlabel = gtk_label_new("dx");
- gtk_widget_set_tooltip_text(xspinlabel, "stretch drawing in x-direction");
- gtk_box_append(GTK_BOX(hbox3), xspinlabel);
- xspinbutton = gtk_spin_button_new_with_range(0, 99, 1);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(xspinbutton), (double)xspacing);
- g_signal_connect(G_OBJECT(xspinbutton), "value_changed", G_CALLBACK(xspin_changed), NULL);
- gtk_box_append(GTK_BOX(hbox3), xspinbutton);
- /* stretch drawing in y dir */
- yspinlabel = gtk_label_new("dy");
- gtk_widget_set_tooltip_text(yspinlabel, "stretch drawing in y-direction");
- gtk_box_append(GTK_BOX(hbox3), yspinlabel);
- yspinbutton = gtk_spin_button_new_with_range(0, 99, 1);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(yspinbutton), (double)yspacing);
- g_signal_connect(G_OBJECT(yspinbutton), "value_changed", G_CALLBACK(yspin_changed), NULL);
- gtk_box_append(GTK_BOX(hbox3), yspinbutton);
- /* at every click, advance positioning mode, the type of node placament */
- pos1 = gtk_label_new("pos");
- gtk_widget_set_tooltip_text(pos1, "positioning mode");
- gtk_box_append(GTK_BOX(hbox3), pos1);
- posbutton = gtk_spin_button_new_with_range(1, 4, 1);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(posbutton), (double)postype);
- g_signal_connect(G_OBJECT(posbutton), "value_changed", G_CALLBACK(pos_changed), NULL);
- gtk_box_append(GTK_BOX(hbox3), posbutton);
- /* draw spline edges or normal */
- check1 = gtk_check_button_new_with_label("splines");
- /* */
- if (option_splines) {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(check1), TRUE);
- } else {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(check1), FALSE);
- }
- gtk_widget_set_tooltip_text(check1, "edge line splines");
- /* routine */
- g_signal_connect(G_OBJECT(check1), "toggled", G_CALLBACK(check1_toggle), NULL);
- gtk_box_append(GTK_BOX(hbox3), check1);
- dummy1 = gtk_check_button_new_with_label("dummy's");
- /* */
- if (option_drawdummy) {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(dummy1), TRUE);
- } else {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(dummy1), FALSE);
- }
- gtk_widget_set_tooltip_text(dummy1, "show dummy nodes");
- /* routine */
- g_signal_connect(G_OBJECT(dummy1), "toggled", G_CALLBACK(dummy1_toggle), NULL);
- gtk_box_append(GTK_BOX(hbox3), dummy1);
- /* area with a text message */
- entry1 = gtk_text_view_new();
- gtk_widget_set_hexpand(entry1, TRUE);
- entry1buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry1));
- gtk_text_buffer_set_text(entry1buffer, "GML4GTK is GNU GPL free software to copy, share and improve", -1);
- gtk_text_view_set_editable(GTK_TEXT_VIEW(entry1), FALSE);
- gtk_widget_set_tooltip_text(entry1, "status information");
- /* monospace font for the text messages and font can be changed */
- gtk_text_view_set_monospace(GTK_TEXT_VIEW(entry1), TRUE);
- /* todo add routines */
- gtk_box_append(GTK_BOX(hbox3), entry1);
- /* next vertical area for options */
- vbox4 = gtk_box_new(GTK_ORIENTATION_VERTICAL, /* spacing */ 0);
- gtk_widget_set_vexpand(vbox4, FALSE);
- gtk_box_append(GTK_BOX(vbox3), vbox4);
- hbox4 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, /* spacing */ 0);
- gtk_widget_set_hexpand(hbox4, TRUE);
- gtk_box_append(GTK_BOX(vbox4), hbox4);
- /* add the options below */
- /* the type of vertical levels node placement */
- rank1 = gtk_label_new("rank");
- gtk_widget_set_tooltip_text(rank1, "dfs/bfs/topological levels");
- gtk_box_append(GTK_BOX(hbox4), rank1);
- /* spin to change rank type note that in gtk2 it is a (GtkObject *) and in gtk3 a (GtkAdjustment *) */
- rankbutton = gtk_spin_button_new_with_range(1, 3, 1);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(rankbutton), (double)ranktype);
- g_signal_connect(G_OBJECT(rankbutton), "value_changed", G_CALLBACK(rank_changed), NULL);
- gtk_box_append(GTK_BOX(hbox4), rankbutton);
- /* the type of barycenter to reduce edge crossings */
- barylabel = gtk_label_new("bary");
- gtk_widget_set_tooltip_text(barylabel, "barycenter type");
- gtk_box_append(GTK_BOX(hbox4), barylabel);
- /* spin to change barycenter type note that in gtk2 it is a (GtkObject *) and in gtk3 a (GtkAdjustment *) */
- barybutton = gtk_spin_button_new_with_range(1, 5, 1);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(barybutton), (double)barytype);
- g_signal_connect(G_OBJECT(barybutton), "value_changed", G_CALLBACK(bary_changed), NULL);
- gtk_box_append(GTK_BOX(hbox4), barybutton);
- /* edgelabels on/off */
- elabel1 = gtk_check_button_new_with_label("elabel");
- /* */
- if (option_edgelabels) {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(elabel1), TRUE);
- } else {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(elabel1), FALSE);
- }
- gtk_widget_set_tooltip_text(elabel1, "edgelabels on/off");
- /* routine */
- g_signal_connect(G_OBJECT(elabel1), "toggled", G_CALLBACK(elabel1_toggle), NULL);
- gtk_box_append(GTK_BOX(hbox4), elabel1);
- /* labels on/off */
- label1 = gtk_check_button_new_with_label("labels");
- /* */
- if (option_labels) {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(label1), TRUE);
- } else {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(label1), FALSE);
- }
- gtk_widget_set_tooltip_text(label1, "labels on/off");
- /* routine */
- g_signal_connect(G_OBJECT(label1), "toggled", G_CALLBACK(label1_toggle), NULL);
- gtk_box_append(GTK_BOX(hbox4), label1);
- /* node names on/off */
- nnames1 = gtk_check_button_new_with_label("names");
- /* */
- if (option_nnames) {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(nnames1), TRUE);
- } else {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(nnames1), FALSE);
- }
- gtk_widget_set_tooltip_text(nnames1, "node names instead of labels");
- /* routine */
- g_signal_connect(G_OBJECT(nnames1), "toggled", G_CALLBACK(nnames1_toggle), NULL);
- gtk_box_append(GTK_BOX(hbox4), nnames1);
- /* popup labels on/off */
- popup1 = gtk_check_button_new_with_label("popup");
- /* */
- if (option_popup) {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(popup1), TRUE);
- } else {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(popup1), FALSE);
- }
- gtk_widget_set_tooltip_text(popup1, "popup labels on/off");
- /* routine */
- g_signal_connect(G_OBJECT(popup1), "toggled", G_CALLBACK(popup1_toggle), NULL);
- gtk_box_append(GTK_BOX(hbox4), popup1);
- /* mirror y on/off */
- mirrory1 = gtk_check_button_new_with_label("mirror");
- /* */
- if (option_mirrory) {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(mirrory1), TRUE);
- } else {
- gtk_check_button_set_active(GTK_CHECK_BUTTON(mirrory1), FALSE);
- }
- gtk_widget_set_tooltip_text(mirrory1, "mirror drawing in y direction");
- /* routine */
- g_signal_connect(G_OBJECT(mirrory1), "toggled", G_CALLBACK(mirrory1_toggle), NULL);
- gtk_box_append(GTK_BOX(hbox4), mirrory1);
- gtk_window_present(GTK_WINDOW(mainwindow1));
- return (0);
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1 || GTK_HAVE_API_VERSION_3 == 1)
- int maingtk23(void)
- {
- GtkWidget *vbox1;
- GtkWidget *menubar1;
- GtkWidget *menuitem1;
- GtkWidget *menuitem1_menu;
- GtkWidget *open1; /* open gml file */
- GtkWidget *open2; /* open dot file */
- GtkWidget *open3; /* open vcg file */
- GtkWidget *open4; /* open jgf file */
- GtkWidget *open5; /* open bgv file */
- GtkWidget *svg1;
- GtkWidget *dia1;
- GtkWidget *jgf1;
- GtkWidget *about1;
- GtkWidget *quit1;
- GtkWidget *hbox1;
- GtkWidget *hbox2;
- GtkWidget *vscale1;
- GtkWidget *vscale2;
- GtkWidget *hscale1;
- GtkWidget *hbox3;
- GtkWidget *xspinlabel;
- GtkAdjustment *xspinadjustment;
- GtkWidget *xspinbutton;
- GtkWidget *yspinlabel;
- GtkAdjustment *yspinadjustment;
- GtkWidget *yspinbutton;
- GtkWidget *pos1;
- GtkAdjustment *posadjustment;
- GtkWidget *check1;
- GtkWidget *dummy1;
- GtkWidget *rank1;
- GtkAdjustment *rankadjustment;
- GtkWidget *rankbutton;
- GtkWidget *entry1;
- GtkWidget *barylabel;
- GtkAdjustment *baryadjustment;
- GtkWidget *barybutton;
- /* GtkWidget *elabel1; is global */
- GtkWidget *label1;
- GtkWidget *nnames1;
- GtkWidget *popup1;
- GtkWidget *mirrory1;
- GtkWidget *menuitem2;
- GtkWidget *menuitem2_menu;
- GtkWidget *fullscreen1;
- GtkWidget *unfullscreen1;
- #ifdef WIN32
- GtkWidget *activate1;
- #endif
- /* top level outer window */
- mainwindow1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- /* make sure to exit oke. */
- g_signal_connect(G_OBJECT(mainwindow1), "destroy", G_CALLBACK(top_level_window_main_quit), NULL);
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* needed for the cairo drawing */
- gtk_widget_set_app_paintable(mainwindow1, TRUE);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- /* set_app_paintable() here causes trouble with the gtk+-3 gui */
- #endif
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* pre-set some size */
- gtk_window_set_default_size(GTK_WINDOW(mainwindow1), TOP_LEVEL_WINDOW_XSIZE, TOP_LEVEL_WINDOW_YSIZE);
- /* --- */
- /* vbox1 is a menu bar */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- vbox1 = gtk_vbox_new( /* homogeneous */ FALSE, /* spacing */ 0);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, /* spacing */ 0);
- #endif
- gtk_container_add(GTK_CONTAINER(mainwindow1), vbox1);
- /* --- */
- /* menu bar in vbox1 */
- menubar1 = gtk_menu_bar_new();
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ menubar1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- /* --- */
- /* menu items in menu bar in vbox1 */
- menuitem1 = gtk_menu_item_new_with_mnemonic("File");
- gtk_container_add(GTK_CONTAINER(menubar1), menuitem1);
- /* --- */
- /* 'file' sub menu in menu items in menu bar in vbox1 */
- menuitem1_menu = gtk_menu_new();
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem1), menuitem1_menu);
- /* --- */
- /* 'open' in 'file' sub menu in menu items in menu bar in vbox1 */
- open2 = gtk_menu_item_new_with_mnemonic("Open DOT graph");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), open2);
- /* run this routine when selected 'open' in 'file' menu */
- g_signal_connect(G_OBJECT(open2), "activate", G_CALLBACK(on_top_level_window_open2_activate), NULL);
- /* 'open' in 'file' sub menu in menu items in menu bar in vbox1 */
- open1 = gtk_menu_item_new_with_mnemonic("Open GML graph");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), open1);
- /* run this routine when selected 'open' in 'file' menu */
- g_signal_connect(G_OBJECT(open1), "activate", G_CALLBACK(on_top_level_window_open1_activate), NULL);
- /* 'open' in 'file' sub menu in menu items in menu bar in vbox1 */
- open3 = gtk_menu_item_new_with_mnemonic("Open CI graph");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), open3);
- /* run this routine when selected 'open' in 'file' menu */
- g_signal_connect(G_OBJECT(open3), "activate", G_CALLBACK(on_top_level_window_open3_activate), NULL);
- /* 'open' in 'file' sub menu in menu items in menu bar in vbox1 */
- open4 = gtk_menu_item_new_with_mnemonic("Open JGF graph");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), open4);
- /* run this routine when selected 'open' in 'file' menu */
- g_signal_connect(G_OBJECT(open4), "activate", G_CALLBACK(on_top_level_window_open4_activate), NULL);
- /* 'open' in 'file' sub menu in menu items in menu bar in vbox1 */
- open5 = gtk_menu_item_new_with_mnemonic("Open BGV graph");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), open5);
- /* run this routine when selected 'open' in 'file' menu */
- g_signal_connect(G_OBJECT(open5), "activate", G_CALLBACK(on_top_level_window_open5_activate), NULL);
- svg1 = gtk_menu_item_new_with_mnemonic("Save as SVG");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), svg1);
- /* run this routine when selected 'svg' in 'file' menu */
- g_signal_connect(G_OBJECT(svg1), "activate", G_CALLBACK(on_top_level_window_svg1_activate), NULL);
- dia1 = gtk_menu_item_new_with_mnemonic("Save as DIA");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), dia1);
- /* run this routine when selected 'dia' in 'file' menu */
- g_signal_connect(G_OBJECT(dia1), "activate", G_CALLBACK(on_top_level_window_dia1_activate), NULL);
- jgf1 = gtk_menu_item_new_with_mnemonic("Save as JGF");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), jgf1);
- /* run this routine when selected 'jgf' in 'file' menu */
- g_signal_connect(G_OBJECT(jgf1), "activate", G_CALLBACK(on_top_level_window_jgf1_activate), NULL);
- /* 'about' in 'file' sub menu in menu items in menu bar in vbox1 */
- about1 = gtk_menu_item_new_with_mnemonic("About");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), about1);
- /* run this routine when selected 'about' in 'file' menu */
- g_signal_connect(G_OBJECT(about1), "activate", G_CALLBACK(show_about), NULL);
- #ifdef WIN32
- /* 'activate' in 'file' sub menu in menu items in menu bar in vbox1 */
- activate1 = gtk_menu_item_new_with_mnemonic("Activate");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), activate1);
- /* run this routine when selected 'activate' in 'file' menu */
- g_signal_connect(G_OBJECT(activate1), "activate", G_CALLBACK(on_top_level_window_activate1_activate), NULL);
- #endif
- /* 'quit' in 'file' sub menu in menu items in menu bar in vbox1 */
- quit1 = gtk_menu_item_new_with_mnemonic("Quit");
- gtk_container_add(GTK_CONTAINER(menuitem1_menu), quit1);
- /* run this routine when selected 'quit' in 'file' menu */
- g_signal_connect(G_OBJECT(quit1), "activate", G_CALLBACK(on_top_level_window_quit1_activate), NULL);
- /* --- */
- /* menu items in menu bar in vbox1 */
- menuitem2 = gtk_menu_item_new_with_mnemonic("Fullscreen");
- gtk_container_add(GTK_CONTAINER(menubar1), menuitem2);
- /* 'fullscreen' sub menu in menu items in menu bar in vbox1 */
- menuitem2_menu = gtk_menu_new();
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem2), menuitem2_menu);
- /* 'fullscreen->fullscreen' in 'fullscreen' sub menu in menu items in menu bar in vbox1 */
- fullscreen1 = gtk_menu_item_new_with_mnemonic("Fullscreen");
- gtk_container_add(GTK_CONTAINER(menuitem2_menu), fullscreen1);
- /* run this routine when selected 'fullscreen->fullscreen in 'fullscreen' menu */
- g_signal_connect(G_OBJECT(fullscreen1), "activate", G_CALLBACK(on_top_level_window_fullscreen1_activate), NULL);
- /* 'fullscreen->normal' in 'fullscreen' sub menu in menu items in menu bar in vbox1 */
- unfullscreen1 = gtk_menu_item_new_with_mnemonic("Normal");
- gtk_container_add(GTK_CONTAINER(menuitem2_menu), unfullscreen1);
- /* run this routine when selected 'fullscreen->normal' in 'fullscreen' menu */
- g_signal_connect(G_OBJECT(unfullscreen1), "activate", G_CALLBACK(on_top_level_window_unfullscreen1_activate), NULL);
- /* -- */
- /*
- * in hbox1
- * left zoom slider
- * drawing area
- * right y slider
- * below x slider
- */
- /* add next area to the vbox1 */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- hbox1 = gtk_hbox_new( /* homogeneous */ FALSE, /* spacing */ 0);
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ hbox1,
- /* expand */ TRUE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, /* spacing */ 0);
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ hbox1,
- /* expand */ TRUE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- #endif
- /* vertical slider in hbox1 for the zoom factor 50% is 1:1 */
- adjvscale1 = gtk_adjustment_new(50, 0, 100, 0, 0, 0);
- #if (GTK_HAVE_API_VERSION_2 == 1)
- vscale1 = gtk_vscale_new(GTK_ADJUSTMENT(adjvscale1));
- g_signal_connect(G_OBJECT(adjvscale1), "value_changed", GTK_SIGNAL_FUNC(on_vscale1_changed), NULL);
- gtk_box_pack_start( /* box */ GTK_BOX(hbox1), /* child */ vscale1,
- /* expand */ FALSE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- gtk_scale_set_draw_value(GTK_SCALE(vscale1), FALSE);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- vscale1 = gtk_scale_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(adjvscale1));
- g_signal_connect(G_OBJECT(adjvscale1), "value_changed", G_CALLBACK(on_vscale1_changed), NULL);
- gtk_box_pack_start( /* box */ GTK_BOX(hbox1), /* child */ vscale1,
- /* expand */ FALSE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- gtk_scale_set_draw_value(GTK_SCALE(vscale1), FALSE);
- #endif
- /* where to draw in hbox1 */
- drawingarea1 = gtk_drawing_area_new();
- gtk_box_pack_start( /* box */ GTK_BOX(hbox1), /* child */ drawingarea1,
- /* expand */ TRUE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- #if (GTK_HAVE_API_VERSION_2 == 1)
- g_signal_connect(G_OBJECT(drawingarea1), "expose_event", G_CALLBACK(on_top_level_window_drawingarea1_expose_event), NULL);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- g_signal_connect(G_OBJECT(drawingarea1), "draw", G_CALLBACK(on_top_level_window_drawingarea1_draw_event), NULL);
- #endif
- /* mouse buttons */
- g_signal_connect(G_OBJECT(drawingarea1), "button-press-event", G_CALLBACK(on_mouse_clicked), NULL);
- g_signal_connect(G_OBJECT(drawingarea1), "motion_notify_event", G_CALLBACK(on_motion_notify_event), NULL);
- /* get button press events to above callback() routines
- * get button 1 press events
- * get mouse pointer movement events
- */
- gtk_widget_set_events((drawingarea1), (GDK_BUTTON_PRESS_MASK | GDK_BUTTON1_MOTION_MASK | GDK_POINTER_MOTION_MASK));
- /* vertical slider in hbox1 for the y position range 0...100% of full image size */
- adjvscale2 = gtk_adjustment_new(0, 0, 100, 0, 0, 0);
- #if (GTK_HAVE_API_VERSION_2 == 1)
- vscale2 = gtk_vscale_new(GTK_ADJUSTMENT(adjvscale2));
- g_signal_connect(G_OBJECT(adjvscale2), "value_changed", GTK_SIGNAL_FUNC(on_vscale2_changed), NULL);
- gtk_box_pack_start( /* box */ GTK_BOX(hbox1), /* child */ vscale2,
- /* expand */ FALSE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- gtk_scale_set_draw_value(GTK_SCALE(vscale2), FALSE);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- vscale2 = gtk_scale_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(adjvscale2));
- g_signal_connect(G_OBJECT(adjvscale2), "value_changed", G_CALLBACK(on_vscale2_changed), NULL);
- gtk_box_pack_start( /* box */ GTK_BOX(hbox1), /* child */ vscale2,
- /* expand */ FALSE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- gtk_scale_set_draw_value(GTK_SCALE(vscale2), FALSE);
- #endif
- /* horizontal scroller 0..100% of drawing size */
- adjhscale1 = gtk_adjustment_new(0, 0, 100, 0, 0, 0);
- #if (GTK_HAVE_API_VERSION_2 == 1)
- hscale1 = gtk_hscale_new(GTK_ADJUSTMENT(adjhscale1));
- g_signal_connect(G_OBJECT(adjhscale1), "value_changed", GTK_SIGNAL_FUNC(on_hscale1_changed), NULL);
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ hscale1,
- /* expand */ FALSE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- gtk_scale_set_draw_value(GTK_SCALE(hscale1), FALSE);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- hscale1 = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT(adjhscale1));
- g_signal_connect(G_OBJECT(adjhscale1), "value_changed", G_CALLBACK(on_hscale1_changed), NULL);
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ hscale1,
- /* expand */ FALSE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- gtk_scale_set_draw_value(GTK_SCALE(hscale1), FALSE);
- #endif
- /* --- */
- /* add next area to the vbox1 */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- hbox2 = gtk_hbox_new( /* homogeneous */ FALSE, /* spacing */ 0);
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ hbox2,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, /* spacing */ 0);
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ hbox2,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- #endif
- /* --- */
- xspinlabel = gtk_label_new("dx");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ xspinlabel,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- gtk_widget_set_tooltip_text(xspinlabel, "stretch drawing in x-direction");
- gtk_widget_show(xspinlabel);
- /* spin to change drawing spread factor. note that in gtk2 it is a (GtkObject *) and in gtk3 a (GtkAdjustment *) */
- xspinadjustment = (GtkAdjustment *) gtk_adjustment_new(xspacing /* initial value */ ,
- 0 /* minimum value */ ,
- 99 /* maximum value */ ,
- 1 /* step increment */ ,
- 1 /* page increment */ ,
- 0 /* page size now *must* be zero */
- );
- xspinbutton = gtk_spin_button_new(xspinadjustment, 1 /* climb rate */ ,
- 0 /* digits achter de comma */ );
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ xspinbutton,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- g_signal_connect(G_OBJECT(xspinadjustment), "value-changed", G_CALLBACK(xspin_changed), (gpointer) xspinbutton);
- yspinlabel = gtk_label_new("dy");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ yspinlabel,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- gtk_widget_set_tooltip_text(yspinlabel, "stretch drawing in y-direction");
- /* spin to change drawing spread factor. note that in gtk2 it is a (GtkObject *) and in gtk3 a (GtkAdjustment *) */
- yspinadjustment = (GtkAdjustment *) gtk_adjustment_new(yspacing /* initial value */ ,
- 0 /* minimum value */ ,
- 99 /* maximum value */ ,
- 1 /* step increment */ ,
- 1 /* page increment */ ,
- 0 /* page size now *must* be zero */
- );
- yspinbutton = gtk_spin_button_new(yspinadjustment, 1 /* climb rate */ ,
- 0 /* digits achter de comma */ );
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ yspinbutton,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- gtk_widget_set_tooltip_text(yspinbutton, "stretch y-direction");
- g_signal_connect(G_OBJECT(yspinadjustment), "value-changed", G_CALLBACK(yspin_changed), (gpointer) yspinbutton);
- /* at every click, advance positioning mode */
- pos1 = gtk_label_new("pos");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ pos1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- gtk_widget_set_tooltip_text(pos1, "positioning mode");
- posadjustment = (GtkAdjustment *) gtk_adjustment_new(postype /* initial value */ ,
- 1 /* minimum value */ ,
- 4 /* maximum value */ ,
- 1 /* step increment */ ,
- 1 /* page increment */ ,
- 0 /* page size now *must* be zero */
- );
- posbutton = gtk_spin_button_new(posadjustment, 1 /* climb rate */ ,
- 0 /* digits achter de comma */ );
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ posbutton,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- g_signal_connect(G_OBJECT(posadjustment), "value-changed", G_CALLBACK(pos_changed), (gpointer) posbutton);
- /* draw spline edges or normal */
- check1 = gtk_check_button_new_with_label("splines");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ check1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- /* */
- if (option_splines) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check1), TRUE);
- } else {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check1), FALSE);
- }
- /* the window arg is not used */
- g_signal_connect(G_OBJECT(check1), "clicked", G_CALLBACK(check1_toggle), (gpointer) mainwindow1);
- gtk_widget_set_tooltip_text(check1, "edge line splines");
- /* draw dummy nodes */
- dummy1 = gtk_check_button_new_with_label("dummy's");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ dummy1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- /* */
- if (option_drawdummy) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dummy1), TRUE);
- } else {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dummy1), FALSE);
- }
- /* the window arg is not used */
- g_signal_connect(G_OBJECT(dummy1), "clicked", G_CALLBACK(dummy1_toggle), (gpointer) mainwindow1);
- gtk_widget_set_tooltip_text(dummy1, "show dummy nodes");
- /* */
- entry1 = gtk_text_view_new();
- entry1buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry1));
- gtk_text_buffer_set_text(entry1buffer, "GML4GTK is free software to copy, share and improve", -1);
- gtk_text_view_set_editable(GTK_TEXT_VIEW(entry1), FALSE);
- gtk_box_pack_start( /* box */ GTK_BOX(hbox2), /* child */ entry1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- gtk_widget_set_tooltip_text(entry1, "status information");
- /*
- * next line with toggle buttons
- */
- /* add next area to the vbox1 */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- hbox3 = gtk_hbox_new( /* homogeneous */ FALSE, /* spacing */ 0);
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ hbox3,
- /* expand */ FALSE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- hbox3 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, /* spacing */ 0);
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ hbox3,
- /* expand */ FALSE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- #endif
- /* level placement */
- rank1 = gtk_label_new("rank");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ rank1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- gtk_widget_set_tooltip_text(rank1, "dfs/bfs/topological levels");
- /* spin to change rank type note that in gtk2 it is a (GtkObject *) and in gtk3 a (GtkAdjustment *) */
- rankadjustment = (GtkAdjustment *) gtk_adjustment_new(ranktype /* initial value */ ,
- 1 /* minimum value */ ,
- 3 /* maximum value */ ,
- 1 /* step increment */ ,
- 1 /* page increment */ ,
- 0 /* page size now *must* be zero */
- );
- rankbutton = gtk_spin_button_new(rankadjustment, 1 /* climb rate */ ,
- 0 /* digits achter de comma */ );
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ rankbutton,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- g_signal_connect(G_OBJECT(rankadjustment), "value-changed", G_CALLBACK(rank_changed), (gpointer) rankbutton);
- /* barycenter */
- barylabel = gtk_label_new("bary");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ barylabel,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- gtk_widget_set_tooltip_text(barylabel, "barycenter type");
- /* spin to change barycenter type note that in gtk2 it is a (GtkObject *) and in gtk3 a (GtkAdjustment *) */
- baryadjustment = (GtkAdjustment *) gtk_adjustment_new(barytype /* initial value */ ,
- 1 /* minimum value */ ,
- 5 /* maximum value */ ,
- 1 /* step increment */ ,
- 1 /* page increment */ ,
- 0 /* page size now *must* be zero */
- );
- barybutton = gtk_spin_button_new(baryadjustment, 1 /* climb rate */ ,
- 0 /* digits achter de comma */ );
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ barybutton,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- g_signal_connect(G_OBJECT(baryadjustment), "value-changed", G_CALLBACK(bary_changed), (gpointer) barybutton);
- /* edgelabels on/off */
- elabel1 = gtk_check_button_new_with_label("elabel");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ elabel1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- /* */
- if (option_edgelabels) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elabel1), TRUE);
- } else {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elabel1), FALSE);
- }
- g_signal_connect(G_OBJECT(elabel1), "clicked", G_CALLBACK(elabel1_toggle), (gpointer) mainwindow1);
- gtk_widget_set_tooltip_text(elabel1, "edgelabels on/off");
- /* labels on/off */
- label1 = gtk_check_button_new_with_label("labels");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ label1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- /* */
- if (option_labels) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(label1), TRUE);
- } else {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(label1), FALSE);
- }
- g_signal_connect(G_OBJECT(label1), "clicked", G_CALLBACK(label1_toggle), (gpointer) mainwindow1);
- gtk_widget_set_tooltip_text(label1, "labels on/off");
- /* node names on/off */
- nnames1 = gtk_check_button_new_with_label("names");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ nnames1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- /* */
- if (option_nnames) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(nnames1), TRUE);
- } else {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(nnames1), FALSE);
- }
- g_signal_connect(G_OBJECT(nnames1), "clicked", G_CALLBACK(nnames1_toggle), (gpointer) mainwindow1);
- gtk_widget_set_tooltip_text(nnames1, "node names instead of labels");
- /* popup labels on/off */
- popup1 = gtk_check_button_new_with_label("popup");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ popup1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- /* */
- if (option_popup) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(popup1), TRUE);
- } else {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(popup1), FALSE);
- }
- g_signal_connect(G_OBJECT(popup1), "clicked", G_CALLBACK(popup1_toggle), (gpointer) mainwindow1);
- gtk_widget_set_tooltip_text(popup1, "popup labels on/off");
- /* mirror y on/off */
- mirrory1 = gtk_check_button_new_with_label("mirror");
- gtk_box_pack_start( /* box */ GTK_BOX(hbox3), /* child */ mirrory1,
- /* expand */ FALSE, /* fill */ FALSE, /* padding */
- PACKPADDING);
- /* */
- if (option_mirrory) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mirrory1), TRUE);
- } else {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mirrory1), FALSE);
- }
- g_signal_connect(G_OBJECT(mirrory1), "clicked", G_CALLBACK(mirrory1_toggle), (gpointer) mainwindow1);
- gtk_widget_set_tooltip_text(mirrory1, "mirror drawing in y direction");
- /*
- * here additional gtk elements
- */
- /* put on screen */
- gtk_widget_show_all(mainwindow1);
- return (0);
- }
- #endif
- int main(int argc, char *argv[])
- {
- int ret = 0;
- char *s = NULL;
- /* check options */
- if (argc > 1) {
- for (ret = 1; ret < argc; ret++) {
- if (strcmp(argv[ret], "--version") == 0) {
- /* print version in config.h set by configure.ac and exit */
- printf("%s\n", PACKAGE_STRING);
- return (0);
- } else if (strcmp(argv[ret], "--debug") == 0) {
- /* set debug flag */
- yydebug = 1;
- printf("%s(): turned on yydebug\n", __func__);
- } else {
- /* add option check here */
- }
- }
- }
- /* */
- dp_meminit();
- /* the program name is saved and also can be gml4gtk4d for debug putput */
- argv0 = argv[0];
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* check the used cairo version at runtime */
- if (cairo_version() < CAIRO_VERSION_ENCODE(1, 17, 4)) {
- /* there is an issue */
- printf("%s(): need at least cairo lib version 1.17.4 and expect blurry text\n", __func__);
- }
- #endif
- /* get the home dir */
- s = getenv("HOME");
- if (s) {
- lastopendir = dp_calloc(1, (strlen(s) + 1));
- strcpy(lastopendir, s);
- lastsavedir = dp_calloc(1, (strlen(s) + 1));
- strcpy(lastsavedir, s);
- } else {
- /* there is no home dir set in env */
- lastopendir = NULL;
- lastsavedir = NULL;
- }
- /* this is depreciated
- * g_type_init();
- * g_thread_init(NULL);
- */
- #if !GLIB_CHECK_VERSION (2, 36, 0)
- /* for GDBus */
- g_type_init();
- #endif
- #if (GTK_HAVE_API_VERSION_0 == 1)
- ret = 0;
- #endif
- #if (GTK_HAVE_API_VERSION_1 == 1)
- ret = 0;
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1 || GTK_HAVE_API_VERSION_3 == 1)
- /*
- * gtk_init (&argc, &argv); in gkt2, gtk3 and gtk_init() in gtk4
- *
- * calls the function gtk_init(gint *argc, gchar ***argv) which will be called in all GTK applications.
- * This sets up a few things for us such as the default visual and color map and then proceeds to call
- * gdk_init(gint *argc, gchar ***argv). This function initializes the library for use, sets up default
- * signal handlers, and checks the arguments passed to your application on the command line,
- * looking for one of the following:
- *
- * * --gtk-module
- * * --g-fatal-warnings
- * * --gtk-debug
- * * --gtk-no-debug
- * * --gdk-debug
- * * --gdk-no-debug
- * * --display
- * * --sync
- * * --no-xshm
- * * --name
- * * --class
- *
- * It removes these from the argument list, leaving anything it does not recognize for your application
- * to parse or ignore. This creates a set of standard arguments accepted by all GTK applications.
- *
- */
- /* do gtk init, gtk will grab the gtk specific options on command line */
- /* gtk 2, 3 */
- {
- if (yydebug) {
- gtk_test_init(&argc, &argv);
- gtk_test_register_all_types();
- /* add here g_test_add_func() */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* only in gtk2 */
- gdk_window_set_debug_updates(TRUE);
- #endif
- /* this does not work:
- * #include "gtkdebug.h"
- * gtk_set_debug_flags(0xffffffff);
- */
- } else {
- gtk_init(&argc, &argv);
- }
- }
- ret = maingtk23();
- if (ret) {
- }
- initialfiles(argc, argv);
- if (ret) {
- }
- /* run the gui */
- gtk_main();
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- {
- GtkApplication *app = NULL;
- /* gtk4 has no args */
- if (yydebug) {
- (void)gtk_test_init(&argc, &argv);
- gtk_test_register_all_types();
- } else {
- (void)gtk_init();
- }
- app = gtk_application_new("www.graphviewer.nl", G_APPLICATION_FLAGS_NONE);
- g_signal_connect(G_OBJECT(app), "activate", G_CALLBACK(maingtk4_activate), NULL);
- ret = g_application_run(G_APPLICATION(app), argc, argv);
- g_object_unref(app);
- if (ret) {
- }
- initialfiles(argc, argv);
- }
- #endif
- /* clear all graph data */
- do_clear_all(0);
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- /* optional memory check report when compiled with -DMEMCHECK */
- dp_memreport();
- return (ret);
- }
- /* scale pos to zvalue */
- static int doscaleit(int val)
- {
- int ret = 0;
- double x = 0.0;
- x = (double)val;
- x = x * zfactor;
- x = round(x);
- ret = (int)x;
- return (ret);
- }
- /* check if a node at mouse pointer position */
- static struct gml_node *is_node_at_xy(int x, int y)
- {
- struct gml_node *found = NULL;
- struct gml_nlist *nl = NULL;
- int x0 = 0;
- int y0 = 0;
- int xs = 0;
- int ys = 0;
- /* first parameters check */
- if (x < 0) {
- return (NULL);
- }
- if (y < 0) {
- return (NULL);
- }
- if (x > drawing_area_xsize) {
- return (NULL);
- }
- if (y > drawing_area_ysize) {
- return (NULL);
- }
- nl = maingraph->nodelist;
- while (nl) {
- /* skip dummy nodes */
- if (nl->node->dummy == 1) {
- nl = nl->next;
- continue;
- }
- /* skip edgelabel nodes */
- if (nl->node->elabel) {
- nl = nl->next;
- continue;
- }
- /* this is a real node and calc screen coords */
- x0 = doscaleit(nl->node->finx - vxmin);
- y0 = doscaleit(nl->node->finy - vymin);
- xs = doscaleit(nl->node->bbx);
- ys = doscaleit(nl->node->bby);
- /* check if on-screen */
- if (x0 < 0 && (x0 + xs) < 0) {
- nl = nl->next;
- continue;
- }
- if (y0 < 0 && (y0 + ys) < 0) {
- nl = nl->next;
- continue;
- }
- if (x0 > drawing_area_xsize) {
- nl = nl->next;
- continue;
- }
- if (y0 > drawing_area_ysize) {
- nl = nl->next;
- continue;
- }
- /* node is on-screen and check wit mouse pointer */
- if ((x > x0 && x < (x0 + xs)) && (y > y0 && y < (y0 + ys))) {
- found = nl->node;
- break;
- }
- /* try other node in drawing */
- nl = nl->next;
- }
- return (found);
- }
- /* make sure there is no popup windows */
- static void no_popup(void)
- {
- if (popupwindow1) {
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- gtk_widget_destroy(popupwindow1);
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- gtk_window_destroy(GTK_WINDOW(popupwindow1));
- #endif
- popupwindow1 = NULL;
- }
- return;
- }
- /* popup the node label text, vars are checked */
- static void popup_nodelabel(struct gml_node *n, cairo_t * crp, int xsize, int ysize)
- {
- int cr = 0;
- int cg = 0;
- int cb = 0;
- int xo = 0;
- int yo = 0;
- PangoLayout *layout = NULL;
- PangoFontDescription *desc = NULL;
- char buf[128];
- char *s = NULL;
- /* name of font to use, example "Sans" */
- const char *default_fontname = DEFAULT_FONTNAME;
- /* name of slant to use, example "Italic", "Oblique", "Roman" */
- const char *default_fontslant = DEFAULT_FONTSLANT;
- /* name of weight to use, example "Bold", "Book", "Light", "Medium", "Semi-bold", "Ultra-light" */
- const char *default_fontweight = DEFAULT_FONTWEIGHT;
- /* name of condensed to use, example "Semi-Condensed", "Condensed" */
- const char *default_fontcondensed = DEFAULT_FONTCONDENSED;
- /* font size to use, example "10", "18", "20" etc. */
- const char *default_fontsize = DEFAULT_FONTSIZE;
- /* fillcolor of node white default or color */
- cr = (n->ncolor & 0x00ff0000) >> 16;
- cg = (n->ncolor & 0x0000ff00) >> 8;
- cb = (n->ncolor & 0x000000ff);
- cairo_set_source_rgb(crp, cr / 255.0, cg / 255.0, cb / 255.0);
- cairo_rectangle(crp, 0, 0, xsize, ysize);
- cairo_fill(crp);
- cairo_stroke(crp);
- /* bordercolor of node black default or color */
- cr = (n->nbcolor & 0x00ff0000) >> 16;
- cg = (n->nbcolor & 0x0000ff00) >> 8;
- cb = (n->nbcolor & 0x000000ff);
- cairo_set_source_rgb(crp, cr / 255.0, cg / 255.0, cb / 255.0);
- cairo_rectangle(crp, 0, 0, xsize, ysize);
- cairo_stroke(crp);
- if (n->hlabel) {
- /* html label */
- on_top_level_window_drawingarea1_expose_event_nodes_html(crp, n);
- } else if (n->rlabel) {
- /* record label */
- /* draw record label */
- on_top_level_window_drawingarea1_expose_event_nodes_record(crp, n);
- } else {
- /* fontcolor of node black default or color */
- cr = (n->fontcolor & 0x00ff0000) >> 16;
- cg = (n->fontcolor & 0x0000ff00) >> 8;
- cb = (n->fontcolor & 0x000000ff);
- /* draw in text color of node */
- cairo_set_source_rgb(crp, cr / 255.0, cg / 255.0, cb / 255.0);
- xo = 2;
- yo = 2;
- /* set start position of text */
- cairo_move_to(crp, n->finx - vxmin + xo, n->finy - vymin + yo);
- layout = pango_cairo_create_layout(crp);
- /* set the text to draw which is 0 terminated */
- pango_layout_set_text(layout, n->nlabel, -1);
- /* set font parameters */
- /* create the fontname description */
- memset(buf, 0, (size_t)128);
- default_fontname = DEFAULT_FONTNAME;
- /* check if node has a specified font slant */
- default_fontslant = DEFAULT_FONTSLANT;
- /* check if node has a specified font weight */
- default_fontweight = DEFAULT_FONTWEIGHT;
- /* check if node has a specified font size */
- default_fontsize = DEFAULT_FONTSIZE;
- /* create the font name string */
- snprintf(buf, (128 - 1), "%s %s %s %s %s", default_fontname,
- default_fontslant, default_fontweight, default_fontcondensed, default_fontsize);
- /* copy string buffer */
- s = uniqstr(buf);
- /* */
- desc = pango_font_description_from_string(s);
- /* */
- pango_layout_set_font_description(layout, desc);
- /* */
- pango_font_description_free(desc);
- /* */
- pango_cairo_update_layout(crp, layout);
- /* draw the text */
- pango_cairo_show_layout(crp, layout);
- /* */
- cairo_stroke(crp);
- g_object_unref(G_OBJECT(layout));
- }
- return;
- }
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* redraw drawing area */
- static gboolean popuparea1_expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer user_data)
- {
- struct gml_node *n = NULL;
- cairo_t *crp = NULL;
- gint w = 0; /* xsize of drawing area */
- gint h = 0; /* ysize of drawing area */
- double zfactor_saved = 0.0;
- int vxmin_saved = 0;
- int vymin_saved = 0;
- if (popupwindow1 == NULL) {
- /* shouldnothappen */
- return (FALSE);
- }
- if (widget) {
- }
- if (event == NULL) {
- return (FALSE);
- }
- /* the user data has the node to draw */
- n = (struct gml_node *)user_data;
- /* get cairo drawing context */
- crp = gdk_cairo_create(event->window);
- if (crp == NULL) {
- /* shouldnothappen */
- return (FALSE);
- }
- /* how large drawing area is */
- (void)gdk_drawable_get_size(event->window, &w, &h);
- if (option_gdebug > 1 || 0) {
- printf("%s(): drawing area size is (%d,%d) node=%p nlabel=\"%s\"\n", __func__, w, h, (void *)n, n->nlabel);
- fflush(stdout);
- }
- if (n == NULL) {
- /* shouldnothappen */
- return (FALSE);
- }
- /* save mainwindow settings */
- zfactor_saved = zfactor;
- vxmin_saved = vxmin;
- vymin_saved = vymin;
- /* draw node label text at 1:1 100% scale */
- zfactor = 1.0;
- vxmin = n->finx;
- vymin = n->finy;
- cairo_scale(crp, zfactor, zfactor);
- /* popup the node label text */
- popup_nodelabel(n, crp, w, h);
- /* restore mainwindow settings */
- zfactor = zfactor_saved;
- vxmin = vxmin_saved;
- vymin = vymin_saved;
- return (FALSE);
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* draw in the popup window the label text */
- static void popuparea1_draw_event_for_gtk4(GtkDrawingArea * area, cairo_t * crdraw, int width, int height, gpointer user_data)
- {
- struct gml_node *n = NULL;
- double zfactor_saved = 0.0;
- int vxmin_saved = 0;
- int vymin_saved = 0;
- if (area) {
- }
- if (popupwindow1 == NULL) {
- /* shouldnothappen */
- return;
- }
- /* the user data has the node to draw */
- n = (struct gml_node *)user_data;
- if (n == NULL) {
- /* shouldnothappen */
- return;
- }
- /* save mainwindow settings */
- zfactor_saved = zfactor;
- vxmin_saved = vxmin;
- vymin_saved = vymin;
- /* draw node label text at 1:1 100% scale */
- zfactor = 1.0;
- vxmin = n->finx;
- vymin = n->finy;
- cairo_scale(crdraw, zfactor, zfactor);
- /* popup the node label text */
- popup_nodelabel(n, crdraw, width, height);
- /* restore mainwindow settings */
- zfactor = zfactor_saved;
- vxmin = vxmin_saved;
- vymin = vymin_saved;
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- /* redraw drawing area */
- static gboolean popuparea1_draw_event(GtkWidget * widget, cairo_t * crdraw, gpointer user_data)
- {
- struct gml_node *n = NULL;
- gint w = 0; /* xsize of drawing area */
- gint h = 0; /* ysize of drawing area */
- cairo_t *crp = NULL;
- double zfactor_saved = 0.0;
- int vxmin_saved = 0;
- int vymin_saved = 0;
- if (popupwindow1 == NULL) {
- /* shouldnothappen */
- return (FALSE);
- }
- if (widget) {
- }
- /* the user data has the node to draw */
- n = (struct gml_node *)user_data;
- if (n == NULL) {
- /* shouldnothappen */
- return (FALSE);
- }
- /* this is a workaround for issue in cairo-lib 1.14.0 with gtk3,
- * cairo.c cairo_destroy() line 305 assert(), (with gtk2 no problem) */
- crp = cairo_reference(crdraw);
- if (crp == NULL) {
- /* shouldnothappen */
- return (FALSE);
- }
- /* how large drawing area is */
- w = gtk_widget_get_allocated_width(popupwindow1);
- h = gtk_widget_get_allocated_height(popupwindow1);
- if (option_gdebug > 1 || 0) {
- printf("%s(): drawing area size is (%d,%d) node %p\n", __func__, w, h, (void *)n);
- fflush(stdout);
- }
- /* save mainwindow settings */
- zfactor_saved = zfactor;
- vxmin_saved = vxmin;
- vymin_saved = vymin;
- /* draw node label text at 1:1 100% scale */
- zfactor = 1.0;
- vxmin = n->finx;
- vymin = n->finy;
- cairo_scale(crp, zfactor, zfactor);
- /* popup the node label text */
- popup_nodelabel(n, crp, w, h);
- /* restore mainwindow settings */
- zfactor = zfactor_saved;
- vxmin = vxmin_saved;
- vymin = vymin_saved;
- return (FALSE);
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* popup window with node label text, (x,y) current mouse pointer */
- static void do_popup(struct gml_node *n, int x, int y)
- {
- int pop = 1;
- GtkWidget *vbox1 = NULL;
- GtkWidget *popuparea1 = (GtkWidget *) 0;
- if (yydebug || 0) {
- printf("%s(): popup window for node at (%d,%d) node ptr %p\n", __func__, x, y, (void *)n);
- }
- /* if there is alreay a popup, keep it that way */
- if (popupwindow1) {
- return;
- }
- /* fresh window */
- popupwindow1 = gtk_window_new();
- /* make sure to exit oke. */
- g_signal_connect(G_OBJECT(popupwindow1), "destroy", G_CALLBACK(no_popup), NULL);
- /* set some title */
- gtk_window_set_title(GTK_WINDOW(popupwindow1), " ");
- /* pre-set size of full sized label text */
- gtk_window_set_default_size(GTK_WINDOW(popupwindow1), (n->fbbx + 5) /* XSIZE */ ,
- n->fbby + 5 /* YSIZE */ );
- /* decorate the window otherwise it will not show up
- * this is a window manager issue and not gtk
- * set to true or false
- */
- gtk_window_set_decorated(GTK_WINDOW(popupwindow1), FALSE);
- /* next vertical area for slider and drawing are */
- vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, /* spacing */ 0);
- gtk_widget_set_hexpand(vbox1, TRUE);
- gtk_widget_set_vexpand(vbox1, TRUE);
- gtk_window_set_child(GTK_WINDOW(popupwindow1), vbox1);
- /* where to draw in box */
- popuparea1 = gtk_drawing_area_new();
- /* stretch maximal */
- gtk_widget_set_vexpand(popuparea1, TRUE);
- gtk_widget_set_hexpand(popuparea1, TRUE);
- /* add routine for drawing with supplied current node in user data */
- gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(popuparea1), /* function */ popuparea1_draw_event_for_gtk4, /* user_data */
- (gpointer) n, /* destroy */ NULL);
- gtk_box_append(GTK_BOX(vbox1), popuparea1);
- if (pop) {
- /* optional move the popup window here next to the node as in the gtk-3 sourcecode */
- /* the position of the created popup window is determined by the windowmanager */
- }
- gtk_window_present(GTK_WINDOW(popupwindow1));
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* popup window with node label text, (x,y) current mouse pointer */
- static void do_popup(struct gml_node *n, int x, int y)
- {
- GdkWindow *window = NULL;
- GtkWidget *vbox1 = (GtkWidget *) 0;
- GtkWidget *popuparea1 = (GtkWidget *) 0;
- int xx = 0;
- int yy = 0;
- int pop = 1;
- /* if there is alreay a popup, keep it that way */
- if (popupwindow1) {
- return;
- }
- /* top level outer window
- * can also be GTK_WINDOW_POPUP but then window is
- * not managed by window manager
- * with POPUP the popup window is at (0,0) on the screen
- * with TOPLEVEL the window can be at mouse position
- * instead of next to mouse position
- *the positioning of the popup window can be optimized
- */
- if (pop) {
- popupwindow1 = gtk_window_new(GTK_WINDOW_POPUP /* or GTK_WINDOW_TOPLEVEL */ );
- } else {
- popupwindow1 = gtk_window_new( /* GTK_WINDOW_POPUP or */ GTK_WINDOW_TOPLEVEL);
- }
- /* make sure to exit oke. */
- g_signal_connect(G_OBJECT(popupwindow1), "destroy", G_CALLBACK(no_popup), NULL);
- /* needed for the cairo drawing */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* only for gtk-2, not for gtk-3 */
- gtk_widget_set_app_paintable(popupwindow1, TRUE);
- #endif
- /* set some title */
- gtk_window_set_title(GTK_WINDOW(popupwindow1), "label");
- /* pre-set size of full sized label text */
- gtk_window_set_default_size(GTK_WINDOW(popupwindow1), (n->fbbx + 5) /* XSIZE */ ,
- n->fbby + 5 /* YSIZE */ );
- /* decorate the window */
- gtk_window_set_decorated(GTK_WINDOW(popupwindow1), FALSE);
- /* vbox1 */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- vbox1 = gtk_vbox_new( /* homogeneous */ FALSE, /* spacing */ 0);
- gtk_widget_show(vbox1);
- gtk_container_add(GTK_CONTAINER(popupwindow1), vbox1);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, /* spacing */ 0);
- gtk_widget_show(vbox1);
- gtk_container_add(GTK_CONTAINER(popupwindow1), vbox1);
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* todo add gtk-4 support */
- #endif
- /* where to draw in hbox1 */
- popuparea1 = gtk_drawing_area_new();
- gtk_box_pack_start( /* box */ GTK_BOX(vbox1), /* child */ popuparea1,
- /* expand */ TRUE, /* fill */ TRUE, /* padding */
- PACKPADDING);
- gtk_widget_show(popuparea1);
- #if (GTK_HAVE_API_VERSION_2 == 1)
- g_signal_connect(G_OBJECT(popuparea1), "expose_event", G_CALLBACK(popuparea1_expose_event), (gpointer) n);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- g_signal_connect(G_OBJECT(popuparea1), "draw", G_CALLBACK(popuparea1_draw_event), (gpointer) n);
- #endif
- /* the label text drawing is in the expose/draw event */
- if (pop) {
- /* get position of window drawarea where mouse is */
- window = gtk_widget_get_window(drawingarea1);
- gdk_window_get_origin(window, &xx, &yy);
- /* move popup right at node */
- gtk_window_move(GTK_WINDOW(popupwindow1), xx + x + 15, yy + y + 0);
- }
- gtk_widget_show(popupwindow1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* movement of mouse on the drawing area */
- static void on_motion_notify_event(GtkEventControllerMotion * controller, double doublex, double doubley, GtkWidget * widget)
- {
- int x = 0;
- int y = 0;
- int pressed = 0;
- int idx = 0;
- int idy = 0;
- double gdelta = 0.0;
- double gsld = 0.0;
- double val = 0.0;
- int ival = 0;
- double dhw = 0.0;
- double dx = 0.0;
- double dy = 0.0;
- double hw = 0.0;
- double hh = 0.0;
- GdkModifierType state = 0;
- struct gml_node *n = NULL;
- if (widget) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- /* make sure there is no popup windows */
- no_popup();
- return;
- }
- /* get the button 1 pressed status */
- state = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(controller));
- if ((state & GDK_BUTTON1_MASK) != 0) {
- pressed = 1;
- } else {
- pressed = 0;
- }
- /* get (x,y) */
- x = (int)doublex;
- y = (int)doubley;
- if (yydebug || 0) {
- printf("%s(): at (%d,%d) left button pressed is %d\n", __func__, x, y, pressed);
- }
- fflush(stdout);
- /* if button left pressed move the drawing (x,y) offset */
- if (pressed) {
- idx = (mouse_oldx - x);
- idy = (mouse_oldy - y);
- if (option_gdebug || 0) {
- printf("%s(): mouse is at (%d,%d) delta is (%d,%d)\n", __func__, x, y, idx, idy);
- }
- if ((idx == 0) && (idy == 0)) {
- /* no change needed */
- return;
- }
- if (idx != 0) {
- hw = (double)(x);
- dx = (double)(mouse_oldx + vxmin) / zfactor;
- dhw = ((double)(hw + vxmin) / zfactor);
- gdelta = dx - dhw;
- vxmin = vxmin + (int)gdelta;
- if (vxmin < 0) {
- vxmin = 0;
- }
- if (vxmin > maxx) {
- vxmin = maxx;
- }
- /* */
- gsld = (gdelta / maxx);
- gsld = (gsld * 100);
- val = gtk_adjustment_get_value(GTK_ADJUSTMENT(adjhscale1));
- ival = (int)val;
- ival = ival + (int)gsld;
- if (ival < 0) {
- ival = 0;
- }
- if (ival > 100) {
- ival = 100;
- }
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), ival);
- }
- if (idy != 0) {
- hh = (double)(y);
- dy = (double)(mouse_oldy + vymin) / zfactor;
- dhw = (hh + vymin) / zfactor;
- gdelta = dy - dhw;
- vymin = vymin + (int)gdelta;
- if (vymin < 0) {
- vymin = 0;
- }
- if (vymin > maxy) {
- vymin = maxy;
- }
- /* */
- gsld = (gdelta / maxy);
- gsld = (gsld * 100);
- val = gtk_adjustment_get_value(GTK_ADJUSTMENT(adjvscale2));
- ival = (int)val;
- ival = ival + (int)gsld;
- if (ival < 0) {
- ival = 0;
- }
- if (ival > 100) {
- ival = 100;
- }
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), ival);
- }
- /* save */
- mouse_oldx = x;
- mouse_oldy = y;
- /* only redraw needed */
- gtk_widget_queue_draw(drawingarea1);
- }
- /* show popup window with node label text if option is set */
- if (option_popup) {
- /* only if there is no popup */
- /* check if node is at mouse location */
- n = is_node_at_xy(x, y);
- if (n) {
- if (yydebug || 0) {
- printf("%s(): found node at cursor\n", __func__);
- }
- /* node text must have a size */
- if ((n->fbbx > 10) && (n->fbby > 10)) {
- /* popup window with node label text */
- do_popup(n, x, y);
- }
- } else {
- /* make sure there is no popup windows */
- no_popup();
- }
- } else {
- /* make sure there is no popup windows */
- no_popup();
- }
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* dragging drawing when left button 1 is held down */
- static gboolean on_motion_notify_event(GtkWidget * widget, GdkEventMotion * event)
- {
- int x = 0;
- int y = 0;
- int idx = 0;
- int idy = 0;
- double gdelta = 0.0;
- double gsld = 0.0;
- double val = 0.0;
- int ival = 0;
- double dhw = 0.0;
- double dx = 0.0;
- double dy = 0.0;
- double hw = 0.0;
- double hh = 0.0;
- GdkModifierType state = 0;
- struct gml_node *n = NULL;
- /* check if there is node data to draw */
- if (validdata == 0) {
- /* make sure there is no popup windows */
- no_popup();
- return (TRUE);
- }
- if (event == NULL) {
- /* shouldnothappen */
- }
- /* where mouse click is on window and mouse status */
- #if (GTK_HAVE_API_VERSION_2 == 1)
- gdk_window_get_pointer(widget->window, &x, &y, &state);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- if (event) {
- gdk_window_get_device_position(gtk_widget_get_window(widget), event->device, &x, &y, &state);
- } else {
- /* shouldnothappen */
- state = 0;
- x = 0;
- y = 0;
- }
- #endif
- if ((state & GDK_BUTTON1_MASK) != 0) {
- idx = (mouse_oldx - x);
- idy = (mouse_oldy - y);
- if (option_gdebug || 0) {
- printf("%s(): mouse is at (%d,%d) delta is (%d,%d)\n", __func__, x, y, idx, idy);
- fflush(stdout);
- }
- if ((idx == 0) && (idy == 0)) {
- return (TRUE);
- }
- if (idx != 0) {
- hw = (double)(x);
- dx = (double)(mouse_oldx + vxmin) / zfactor;
- dhw = ((double)(hw + vxmin) / zfactor);
- gdelta = dx - dhw;
- vxmin = vxmin + (int)gdelta;
- if (vxmin < 0) {
- vxmin = 0;
- }
- if (vxmin > maxx) {
- vxmin = maxx;
- }
- /* */
- gsld = (gdelta / maxx);
- gsld = (gsld * 100);
- val = gtk_adjustment_get_value(GTK_ADJUSTMENT(adjhscale1));
- ival = (int)val;
- ival = ival + (int)gsld;
- if (ival < 0) {
- ival = 0;
- }
- if (ival > 100) {
- ival = 100;
- }
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), ival);
- }
- if (idy != 0) {
- hh = (double)(y);
- dy = (double)(mouse_oldy + vymin) / zfactor;
- dhw = (hh + vymin) / zfactor;
- gdelta = dy - dhw;
- vymin = vymin + (int)gdelta;
- if (vymin < 0) {
- vymin = 0;
- }
- if (vymin > maxy) {
- vymin = maxy;
- }
- /* */
- gsld = (gdelta / maxy);
- gsld = (gsld * 100);
- val = gtk_adjustment_get_value(GTK_ADJUSTMENT(adjvscale2));
- ival = (int)val;
- ival = ival + (int)gsld;
- if (ival < 0) {
- ival = 0;
- }
- if (ival > 100) {
- ival = 100;
- }
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), ival);
- }
- /* save */
- mouse_oldx = x;
- mouse_oldy = y;
- /* only redraw needed */
- gtk_widget_queue_draw(drawingarea1);
- }
- /* show popup window with node label text if option is set */
- if (option_popup) {
- /* only if there is no popup */
- /* check if node is at mouse location */
- n = is_node_at_xy(x, y);
- if (n) {
- /* node text must have a size */
- if ((n->fbbx > 10) && (n->fbby > 10)) {
- /* popup window with node label text */
- do_popup(n, x, y);
- }
- } else {
- /* make sure there is no popup windows */
- no_popup();
- }
- } else {
- /* make sure there is no popup windows */
- no_popup();
- }
- return (TRUE);
- }
- #endif
- /* mouse click on drawing area
- *
- * guint event->type has this info
- * enum GdkEventType
- * {
- * .
- * GDK_BUTTON_PRESS = 4, (single click)
- * GDK_2BUTTON_PRESS = 5, (double click)
- * GDK_3BUTTON_PRESS = 6, (triple click)
- * GDK_BUTTON_RELEASE = 7, (released)
- * ...
- * };
- * which button is clicked is in guint event->button;
- * the button which was pressed or released, numbered from 1 to 5.
- * Normally button 1 is the left mouse button,
- * 2 is the middle button, and 3 is the right button.
- * On 2-button mice, the middle button can often be simulated
- * by pressing both mouse buttons together.
- * for dragging the mouse (x,y) is saved.
- */
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* on_mouse_clicked is handled in motion notify */
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- static gboolean on_mouse_clicked(GtkWidget * widget, GdkEventButton * event, gpointer user_data)
- {
- int eventbutton = 0;
- double dx = 0.0;
- double dy = 0.0;
- int nx = 0;
- int ny = 0;
- int ex = 0;
- int ey = 0;
- if (widget) {
- }
- if (user_data) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- return (TRUE);
- }
- /* get where clicked in the drawing */
- ex = (event->x);
- ey = (event->y);
- dx = ((double)ex / zfactor);
- dy = ((double)ey / zfactor);
- nx = ((int)dx) + vxmin;
- ny = ((int)dy) + vymin;
- if (nx) {
- }
- if (ny) {
- }
- /* check the buttons */
- eventbutton = (int)(event->button);
- /* check the buttons after modification */
- if (eventbutton == 1) {
- /* left button drag drawing using motion_notify_event */
- mouse_oldx = ex;
- mouse_oldy = ey;
- return (TRUE);
- }
- if (eventbutton == 2) {
- /* middle button clicked */
- return (TRUE);
- }
- if (eventbutton == 3) {
- /* right button clicked */
- return (TRUE);
- }
- if (eventbutton == 4) {
- /* button 4 clicked */
- return (TRUE);
- }
- if (eventbutton == 5) {
- /* button 5 clicked */
- return (TRUE);
- }
- if (eventbutton == 6) {
- return TRUE;
- }
- if (eventbutton == 7) {
- return TRUE;
- }
- if (eventbutton == 8) {
- /* lower side button */
- return TRUE;
- }
- if (eventbutton == 9) {
- /* upper side button */
- return TRUE;
- }
- /* unknown button */
- return TRUE;
- }
- #endif
- /* debug print layout of one cluster */
- static void do_layout_all_rprint(struct gml_graph *g)
- {
- struct gml_nlist *lnl = NULL;
- char *s = NULL;
- lnl = g->nodelist;
- while (lnl) {
- s = "";
- if (lnl->node->dummy) {
- s = "dummynode";
- }
- if (lnl->node->elabel) {
- s = "edgelabel";
- }
- printf("%s(): node %d is at (%d,%d) %s\n", __func__, lnl->node->nr, lnl->node->relx, lnl->node->rely, s);
- lnl = lnl->next;
- }
- return;
- }
- /* incremental layout */
- static void do_layout_all_r(struct gml_graph *g)
- {
- struct gml_glist *gl = NULL;
- if (g == NULL) {
- return;
- }
- gl = g->subglist;
- while (gl) {
- do_layout_all_r(gl->sg);
- gl = gl->next;
- }
- /* skip the subgraphs */
- if (g->type != SG_CLUSTER) {
- return;
- }
- printf("%s(): calculation layout of cluster `%s' `%s'\n", __func__, g->graphname, g->label);
- /* this are the incremental layout stages */
- /* re-organize nodelist */
- reorg(g);
- /* change cycles in the graph */
- uncycle(g);
- /* re-organize nodelist */
- reorg(g);
- /* determine startnodes */
- if (1) { /* old */
- startnodes(g);
- }
- /* longest path algorithm */
- longestpath(g);
- /* set y level of all nodes */
- ylevels(g);
- /* try to find shorter edges */
- shorteredges(g);
- /* change edge directions downwards */
- edgesdownwards(g, 1);
- /* check length of edges */
- edgelen(g);
- /* doublespace the vertical levels */
- doublespacey(g);
- /* split edges with label into node->label->node */
- edgelabels(g, 0);
- /* after edge label nodes are created:
- * calculate (x,y) size of text area
- */
- static_maingtk_textsizes();
- /* split longer edges */
- splitedges(g, /* before bary */ 0);
- /* create level node count data */
- nodecounts(g);
- /* determine startnodes */
- if (0) {
- startnodes(g);
- }
- /* run barycenter using defaults (0,0) or a value */
- barycenter(g, 0, 0);
- /* force postype */
- postype = 1;
- /* set the value for the new pos type */
- gtk_spin_button_set_value((GtkSpinButton *) posbutton, postype);
- improve_positions(g);
- /* add final() edgeconn() posz() */
- /* print results */
- if (yydebug || 0) {
- do_layout_all_rprint(g);
- }
- return;
- }
- /* run all stages of the layout
- * todo pos_changed() should be able to call this
- * with only updating positionings and no barycenter etc.
- */
- static void do_layout_all(struct gml_graph *g)
- {
- struct gml_glist *gl = NULL;
- int modus = 0; /* barycenter layout mode 1 0 */
- /* sync() is on GNU/Linux, maybe not on others */
- #ifdef HAVE_SYNC
- #ifdef sync
- /* sync() found */
- #else
- /* gcc-12 analyzer says issue here */
- /* sync() still not found. manual added now. */
- extern void sync(void);
- #endif
- /* maybe safer on Linux to sync() now because next may need much extra memory */
- sync();
- #endif
- /* this is also valid c
- * int c=0;
- * int javascript=0;
- * if (c --> javascript) c++;
- */
- if (incrlayout /* 0 */ && maingraph->tnclusters) {
- /* todo fixup for modus */
- printf("%s(): doing incremental layout for %d clusters\n", __func__, maingraph->tnclusters);
- /* prepare */
- prepincr(g);
- /* set edges with labels */
- prepel(g);
- /* recursively layout the clusters */
- gl = maingraph->subglist;
- while (gl) {
- do_layout_all_r(gl->sg);
- gl = gl->next;
- }
- } else {
- /* this are the regular layout stages */
- /* prepare */
- prep(g);
- /* set edges with labels */
- prepel(g);
- /* re-organize nodelist */
- reorg(g);
- /* change cycles in the graph */
- uncycle(g);
- /* re-organize nodelist */
- reorg(g);
- /* determine startnodes */
- if (modus == 0 || 1) {
- startnodes(g);
- }
- /* find longest path */
- longestpath(g);
- /* set y level of all nodes */
- ylevels(g);
- /* try to find shorter edges */
- shorteredges(g);
- /* change edge directions downwards */
- edgesdownwards(g, 1);
- /* mark same edges */
- checksame(g);
- if (modus == 1) {
- /* split same edges */
- splitsame(g);
- }
- /* check length of edges */
- edgelen(g);
- if (modus == 0) {
- /* doublespace the vertical levels */
- doublespacey(g);
- /* split edges with label into node->label->node */
- edgelabels(g, 0);
- }
- /* after edge label nodes are created:
- * calculate (x,y) size of text area
- */
- static_maingtk_textsizes();
- if (modus == 0) {
- /* split longer edges */
- splitedges(g, /* before bary */ 0);
- }
- /* create level node count data */
- nodecounts(g);
- /* run barycenter using defaults (0,0) or a value */
- barycenter(g, 100, 100);
- if (modus == 1) {
- /* doublespace the vertical levels */
- doublespaceyafter(g);
- /* split longer edges */
- splitedgesafter(g);
- /* create level node count data */
- nodecountsafter(g);
- }
- /* update startnodes */
- startnodesafter(g);
- /* final */
- finalafter(g);
- /* run priority algorithm */
- improve_positions(g);
- /* final (x,y) positioning of nodes/edges */
- /* todo draw errors with dummy node routing */
- /* todo works with node names and gcc data but not with irregular larger labels */
- finalxy(g);
- /* calculate edge connections */
- /* XXXX tofix this can fail */
- edgeconnections(g);
- /* update sub parts of drawing */
- positionz(g);
- }
- return;
- }
- /* run all stages of the layout */
- static void do_relayout_all(struct gml_graph *g)
- {
- /* also possible to re-layout only 1 specific subgraph */
- if (g) {
- }
- do_clear_all( /* keep raw data */ 1);
- do_layout_all(maingraph);
- fflush(stdout);
- /* set sliders to defaults */
- sliders_default();
- /* fit drawing in window */
- dofit();
- validdata = 1;
- /* update status text */
- update_status_text(NULL);
- return;
- }
- /* clear all memory used by the graph data
- * if mode==0 clear all data
- * if mode==1 keep some data
- * used in a re-layout
- */
- static void do_clear_all(int mode)
- {
- /* no draw data */
- validdata = 0;
- if (mode == 0) {
- /* clear db with strings */
- clear_uniqstr();
- /* clear db with nodes */
- clear_uniqnode(NULL);
- /* clear db with graph pointers */
- clear_uniqgraph(NULL);
- }
- /* clear db with nodes */
- clear_uniqnode2(NULL);
- if (maingraph) {
- /* clear optional record label and html of node */
- if (mode == 0) {
- /* clear all data */
- clear_rlabel_r(maingraph);
- clear_hlabel_r(maingraph);
- }
- /* clear number of edges between level n and n+1 */
- clear_nume_r(maingraph);
- /* clear number of nodes at level */
- clear_nnl_r(maingraph);
- /* clear arrays in/out edges */
- clear_ioedges_r(maingraph);
- /* clear count of crossing edges at level */
- clear_numce_r(maingraph);
- /* clear self-edges list */
- clear_selfedgesnodelist_r(maingraph);
- /* clear single nodes list */
- clear_singlenodelist_r(maingraph);
- /* clear startnodes array */
- clear_startnodes_r(maingraph);
- /* clear nodes list and its data
- * if mode<>0 then keep record label data
- * that will be re-used at doing re-layout
- * if mode==0 clear the rlabel data
- */
- clear_nodelist_r(maingraph, mode);
- /* clear edges list */
- clear_edgelist_r(maingraph);
- /* clear bubbling algorithm */
- clear_bubbling(maingraph);
- if (mode == 0) {
- /* clear optional edge label data */
- clear_edgelabeldata(maingraph);
- /* clear subgraphs and optional summary node */
- clear_sg(maingraph);
- /* clear input nodes */
- clear_rawnodelist(maingraph);
- /* clear input edges */
- clear_rawedgelist(maingraph);
- /* clear main graph structure */
- maingraph = dp_free(maingraph);
- if (maingraph) {
- }
- }
- }
- return;
- }
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* finally stop the gui */
- static void top_level_window_main_quit(void)
- {
- do_clear_all(0);
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- /* run the gtk internal routine to stop gtk_main() which is a for(){} loop */
- gtk_main_quit();
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- static void fullscreen_changed(GSimpleAction * action, GVariant * value, gpointer win)
- {
- if (g_variant_get_boolean(value)) {
- gtk_window_maximize(GTK_WINDOW(win));
- } else {
- gtk_window_unmaximize(GTK_WINDOW(win));
- }
- g_simple_action_set_state(action, value);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* use full screen */
- static void on_top_level_window_fullscreen1_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- if (menuitem) {
- }
- if (user_data) {
- }
- gtk_window_fullscreen(GTK_WINDOW(mainwindow1));
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* use screen in a window */
- static void on_top_level_window_unfullscreen1_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- if (menuitem) {
- }
- if (user_data) {
- }
- gtk_window_unfullscreen(GTK_WINDOW(mainwindow1));
- return;
- }
- #endif
- /* for windos activate product message */
- #ifdef WIN32
- #if (GTK_HAVE_API_VERSION_4 == 1)
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* for the windows version */
- static void on_top_level_window_activate1_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *edialog = NULL;
- char *message = "GNU GPL Free GNU/Linux software can just be used without limitations.\n"
- "There is no need for product activation or a product key.\n"
- "This program does not have telemetry using internet.\n"
- "This program does not create or change files on your computer.\n"
- "This program does not use cookies or run javascript.\n"
- "This program is free to copy, share or improve with source code.\n";
- if (menuitem) {
- }
- if (user_data) {
- }
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message);
- gtk_widget_show(edialog);
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- return;
- }
- #endif
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* parse the file */
- static void open2_response_cb_fn(char *inputfilename, char *binputfilename)
- {
- gzFile f; /* the zipped file stream */
- GtkWidget *dialog = NULL;
- /* binputfilename is the short filename and should not be numm */
- /* open file to parse */
- errno = 0;
- /* open zipped or unzipped file as file stream */
- f = gzopen(inputfilename, "rb");
- if (f == NULL || 0) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Cannot open file %s", inputfilename);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 1;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the dot data */
- if (gmlparse(maingraph, f, inputfilename, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- fflush(stdout);
- gzclose(f);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- fflush(stdout);
- gzclose(f);
- /* set the basename of file as window title /tmp/foo.dot has window title foo.dot */
- if (binputfilename) {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), binputfilename);
- } else {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), inputfilename);
- }
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, inputfilename);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- /* set sliders to defaults */
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- return;
- }
- /* run dialog and set bool done to TRUE if ready */
- static void open2_response_cb(GtkDialog * dialog, int response_id, gpointer data)
- {
- gboolean *done = data; /* bool to set is passed on at call */
- GListModel *files = NULL;
- guint i = 0;
- guint n = 0;
- GFile *file = NULL;
- GFile *folder = NULL;
- char *uri = NULL;
- char *file_chooser_dir = NULL;
- char *inputfilename = NULL;
- char *file_chooser_filename = NULL;
- char *bname = NULL;
- if (response_id == GTK_RESPONSE_OK) {
- /* scan the list with selected files */
- files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog));
- n = g_list_model_get_n_items(files);
- if (yydebug || 0) {
- g_print("%s(): selected %d files\n", __func__, n);
- }
- for (i = 0; i < n; i++) {
- file = g_list_model_get_item(files, i);
- uri = g_file_get_uri(file);
- /* option here
- * the uri is like file:///bin/true
- * this allows for network uri
- * as https://graphviewer.nl/data/example.dot
- */
- if (uri == NULL) {
- g_print("%s(): file %d has nil name\n", __func__, i);
- } else {
- if (strlen(uri) == 0) {
- g_print("%s(): file %d has empty name \"\"\n", __func__, i);
- } else {
- if (i != 0) {
- g_print("%s(): skipped file %d with name %s\n", __func__, i, uri);
- } else {
- /* this is the first file to read
- * uri is file:///bin/foo
- * g_file_get_parse_name(file) is /bin/foo
- * g_file_get_basename(file) is foo
- * g_file_get_path(file) is /bin/foo
- */
- /* update directory of chosen file */
- folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (folder) {
- file_chooser_dir = g_file_get_parse_name(folder);
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- g_free(file_chooser_dir);
- file_chooser_dir = NULL;
- }
- g_object_unref(folder);
- }
- /* copy filename */
- file_chooser_filename = g_file_get_parse_name(file);
- if (file_chooser_filename) {
- if (strlen(file_chooser_filename)) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- } else {
- g_print("%s(): empty filename\n", __func__);
- }
- bname = g_file_get_basename(file);
- /* read and parse the file */
- open2_response_cb_fn(file_chooser_filename, bname);
- if (bname) {
- g_free(bname);
- bname = NULL;
- };
- /* there could have been a parse error */
- g_free(file_chooser_filename);
- file_chooser_filename = NULL;
- }
- /* print the derived filenames */
- if (yydebug || 0) {
- g_print("%s(): %s %s %s %s %s\n", __func__, g_file_get_parse_name(file),
- g_file_get_basename(file), uri, g_file_get_path(file), g_file_get_parse_name(folder));
- }
- }
- }
- g_free(uri);
- uri = NULL;
- }
- g_object_unref(file);
- }
- g_object_unref(files);
- } else {
- /* no file selected */
- if (yydebug || 0) {
- g_print("%s(): open dialog was closed\n", __func__);
- }
- }
- /* inicate this dialog is finished in passed on var */
- *done = TRUE;
- g_main_context_wakeup(NULL);
- return;
- }
- /* open dot file */
- static void open2_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- gboolean multiple = FALSE; /* if TRUE multiple files can be selected as extended feature */
- GtkWidget *dialog = NULL;
- GtkFileFilter *filter = NULL;
- gboolean done = FALSE; /* indicator dialog is finished */
- if (action) {
- }
- if (parameter) {
- }
- if (user_data) {
- }
- /* see the testcase in gtk-4 testfilechooser.c */
- dialog = g_object_new(GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_OPEN, "select-multiple", multiple, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Open gml graph file");
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), ("_Cancel"), GTK_RESPONSE_CANCEL, ("_Open"), GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- /* the callback will set bool done to TRUE if ready */
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(open2_response_cb), (gpointer) & done);
- /* Filters */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "All Files");
- gtk_file_filter_add_pattern(filter, "*");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "gml");
- gtk_file_filter_add_pattern(filter, "*.gml");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- /* this are the gzipped graph files */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "gml.gz");
- gtk_file_filter_add_pattern(filter, "*.gml.gz");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- if (lastopendir) {
- set_current_folder(GTK_FILE_CHOOSER(dialog), lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- /* run dialog and wait until it is ready */
- while (done == FALSE) {
- g_main_context_iteration(NULL, TRUE);
- }
- gtk_window_destroy(GTK_WINDOW(dialog));
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* 'open' in 'file' menu activated - sub menu in menu items in menu bar in vbox1 */
- static void on_top_level_window_open1_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *edialog = (GtkWidget *) 0;
- GtkWidget *pdialog = (GtkWidget *) 0;
- GtkWidget *dialog = (GtkWidget *) 0;
- char *file_chooser_filename = (char *)0;
- char *file_chooser_dir = (char *)0;
- GtkFileChooser *chooser = NULL;
- char *inputfilename = (char *)0;
- char *baseinputfilename = (char *)0;
- char *baseinputfilename2 = (char *)0;
- gzFile fgml = (gzFile) 0;
- char *bname = NULL;
- int cnt = 0;
- if (menuitem) {
- }
- if (user_data) {
- }
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select GML Graph File", 0, /* parent_window */
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select GML Graph File", GTK_WINDOW(mainwindow1) /* parent_window */
- ,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
- #endif
- chooser = GTK_FILE_CHOOSER(dialog);
- /* use same dir if opened in earlier dir */
- if (lastopendir) {
- gtk_file_chooser_set_current_folder(chooser, lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- /* run the window to select a input file */
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- /* open button */
- file_chooser_filename = (char *)gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- file_chooser_dir = (char *)gtk_file_chooser_get_current_folder(chooser);
- } else {
- /* cancel button */
- (void)gtk_widget_destroy(dialog);
- return;
- }
- /* */
- (void)gtk_widget_destroy(dialog);
- /* update last-used-dir */
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_dir);
- }
- /* copy the input filename from gtk */
- if (file_chooser_filename) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_filename);
- } else {
- return;
- }
- /* set filename in window */
- bname = g_path_get_basename(inputfilename);
- baseinputfilename2 = dp_calloc(1, (strlen(bname) + 1));
- strcpy(baseinputfilename2, bname);
- /* not dp_free() because gtk allocated */
- g_free(bname);
- /* open file to parse */
- errno = 0;
- fgml = gzopen(inputfilename, "r");
- if (fgml == (gzFile) 0 || 0) {
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "Cannot open file %s for reading (%s)", inputfilename, g_strerror(errno));
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- if (inputfilename) {
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 0;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the gml data
- * the next line is a bug not detected by the source code checker software
- * if (gmlparse(maingraph, fgml, baseinputfilename2) > 0 && 0 < gmlparse(maingraph, fgml, baseinputfilename2))
- * such kind of bugs do happen and can have big impact on the functionality
- */
- if (gmlparse(maingraph, fgml, baseinputfilename2, argv0) != 0) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- pdialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_dialog_run(GTK_DIALOG(pdialog));
- gtk_widget_destroy(pdialog);
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- gzclose(fgml);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- gzclose(fgml);
- bname = g_path_get_basename(inputfilename);
- baseinputfilename = uniqstr(bname);
- /* not dp_free because gtk allocated */
- g_free(bname);
- gtk_window_set_title(GTK_WINDOW(mainwindow1), baseinputfilename);
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, baseinputfilename2);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- #if (GTK_HAVE_API_VERSION_4 == 1)
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- cnt = 1000;
- while (gtk_events_pending()) {
- cnt--;
- if (cnt > 0) {
- gtk_main_iteration();
- /* this updates the status text */
- }
- }
- #endif
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- while (gtk_main_iteration()) {
- /* this should update the status text */ ;
- }
- /* set sliders to defaults */
- zfactor = 1.0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale1), 50);
- vxmin = 0;
- vymin = 0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), 0);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), 0);
- /* filename is not saved */
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* filename is not saved */
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* parse the file */
- static void open5_response_cb_fn(char *inputfilename, char *binputfilename)
- {
- gzFile f; /* the zipped file stream */
- GtkWidget *dialog = NULL;
- /* binputfilename is the short filename and should not be numm */
- /* open file to parse */
- errno = 0;
- /* open zipped or unzipped file as file stream */
- f = gzopen(inputfilename, "rb");
- if (f == NULL || 0) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Cannot open file %s", inputfilename);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 1;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the jgf data */
- if (bgvparse(maingraph, f, inputfilename, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- fflush(stdout);
- gzclose(f);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- fflush(stdout);
- gzclose(f);
- /* set the basename of file as window title /tmp/foo.dot has window title foo.dot */
- if (binputfilename) {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), binputfilename);
- } else {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), inputfilename);
- }
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, inputfilename);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- /* set sliders to defaults */
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- return;
- }
- /* run dialog and set bool done to TRUE if ready */
- static void open5_response_cb(GtkDialog * dialog, int response_id, gpointer data)
- {
- gboolean *done = data; /* bool to set is passed on at call */
- GListModel *files = NULL;
- guint i = 0;
- guint n = 0;
- GFile *file = NULL;
- GFile *folder = NULL;
- char *uri = NULL;
- char *file_chooser_dir = NULL;
- char *inputfilename = NULL;
- char *file_chooser_filename = NULL;
- char *bname = NULL;
- if (response_id == GTK_RESPONSE_OK) {
- /* scan the list with selected files */
- files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog));
- n = g_list_model_get_n_items(files);
- if (yydebug || 0) {
- g_print("%s(): selected %d files\n", __func__, n);
- }
- for (i = 0; i < n; i++) {
- file = g_list_model_get_item(files, i);
- uri = g_file_get_uri(file);
- /* option here
- * the uri is like file:///bin/true
- * this allows for network uri
- * as https://graphviewer.nl/data/example.dot
- */
- if (uri == NULL) {
- g_print("%s(): file %d has nil name\n", __func__, i);
- } else {
- if (strlen(uri) == 0) {
- g_print("%s(): file %d has empty name \"\"\n", __func__, i);
- } else {
- if (i != 0) {
- g_print("%s(): skipped file %d with name %s\n", __func__, i, uri);
- } else {
- /* this is the first file to read
- * uri is file:///bin/foo
- * g_file_get_parse_name(file) is /bin/foo
- * g_file_get_basename(file) is foo
- * g_file_get_path(file) is /bin/foo
- */
- /* update directory of chosen file */
- folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (folder) {
- file_chooser_dir = g_file_get_parse_name(folder);
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- g_free(file_chooser_dir);
- file_chooser_dir = NULL;
- }
- g_object_unref(folder);
- }
- /* copy filename */
- file_chooser_filename = g_file_get_parse_name(file);
- if (file_chooser_filename) {
- if (strlen(file_chooser_filename)) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- } else {
- g_print("%s(): empty filename\n", __func__);
- }
- bname = g_file_get_basename(file);
- /* read and parse the file */
- open5_response_cb_fn(file_chooser_filename, bname);
- if (bname) {
- g_free(bname);
- bname = NULL;
- };
- /* there could have been a parse error */
- g_free(file_chooser_filename);
- file_chooser_filename = NULL;
- }
- /* print the derived filenames */
- if (yydebug || 0) {
- g_print("%s(): %s %s %s %s %s\n", __func__, g_file_get_parse_name(file),
- g_file_get_basename(file), uri, g_file_get_path(file), g_file_get_parse_name(folder));
- }
- }
- }
- g_free(uri);
- uri = NULL;
- }
- g_object_unref(file);
- }
- g_object_unref(files);
- } else {
- /* no file selected */
- if (yydebug || 0) {
- g_print("%s(): open dialog was closed\n", __func__);
- }
- }
- /* inicate this dialog is finished in passed on var */
- *done = TRUE;
- g_main_context_wakeup(NULL);
- return;
- }
- /* open bgv file */
- static void open5_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- gboolean multiple = FALSE; /* if TRUE multiple files can be selected as extended feature */
- GtkWidget *dialog = NULL;
- GtkFileFilter *filter = NULL;
- gboolean done = FALSE; /* indicator dialog is finished */
- if (action) {
- }
- if (parameter) {
- }
- if (user_data) {
- }
- /* see the testcase in gtk-4 testfilechooser.c */
- dialog = g_object_new(GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_OPEN, "select-multiple", multiple, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Open bgv graph file");
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), ("_Cancel"), GTK_RESPONSE_CANCEL, ("_Open"), GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- /* the callback will set bool done to TRUE if ready */
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(open5_response_cb), (gpointer) & done);
- /* Filters */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "All Files");
- gtk_file_filter_add_pattern(filter, "*");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "bgv");
- gtk_file_filter_add_pattern(filter, "*.bgv");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- /* this are the gzipped graph files */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "bgv.gz");
- gtk_file_filter_add_pattern(filter, "*.bgv.gz");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- if (lastopendir) {
- set_current_folder(GTK_FILE_CHOOSER(dialog), lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- /* run dialog and wait until it is ready */
- while (done == FALSE) {
- g_main_context_iteration(NULL, TRUE);
- }
- gtk_window_destroy(GTK_WINDOW(dialog));
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* 'open' in 'file' menu activated - sub menu in menu items in menu bar in vbox1 */
- static void on_top_level_window_open5_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *edialog = (GtkWidget *) 0;
- GtkWidget *pdialog = (GtkWidget *) 0;
- GtkWidget *dialog = (GtkWidget *) 0;
- char *file_chooser_filename = (char *)0;
- char *file_chooser_dir = (char *)0;
- GtkFileChooser *chooser = NULL;
- char *inputfilename = (char *)0;
- char *baseinputfilename = (char *)0;
- char *baseinputfilename2 = (char *)0;
- gzFile f = NULL;
- char *bname = NULL;
- int cnt = 0;
- if (menuitem) {
- }
- if (user_data) {
- }
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select BGV Graph File", 0, /* parent_window */
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select BGV Graph File", GTK_WINDOW(mainwindow1) /* parent_window */
- ,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
- #endif
- chooser = GTK_FILE_CHOOSER(dialog);
- /* use same dir if opened in earlier dir */
- if (lastopendir) {
- gtk_file_chooser_set_current_folder(chooser, lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- /* run the window to select a input file */
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- /* open button */
- file_chooser_filename = (char *)gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- file_chooser_dir = (char *)gtk_file_chooser_get_current_folder(chooser);
- } else {
- /* cancel button */
- (void)gtk_widget_destroy(dialog);
- return;
- }
- /* */
- (void)gtk_widget_destroy(dialog);
- /* update last-used-dir */
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_dir);
- }
- /* copy the input filename from gtk */
- if (file_chooser_filename) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_filename);
- } else {
- return;
- }
- /* set filename in window */
- bname = g_path_get_basename(inputfilename);
- baseinputfilename2 = dp_calloc(1, (strlen(bname) + 1));
- strcpy(baseinputfilename2, bname);
- /* not dp_free() because gtk allocated */
- g_free(bname);
- /* open file to parse */
- errno = 0;
- f = gzopen(inputfilename, "rb");
- if (f == NULL) {
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "Cannot open file %s for reading (%s)", inputfilename, g_strerror(errno));
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 1;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the bgv data */
- if (bgvparse(maingraph, f, baseinputfilename2, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- pdialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_dialog_run(GTK_DIALOG(pdialog));
- gtk_widget_destroy(pdialog);
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- fflush(stdout);
- gzclose(f);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- gzclose(f);
- bname = g_path_get_basename(inputfilename);
- baseinputfilename = uniqstr(bname);
- /* not dp_free() because gtk allocated */
- g_free(bname);
- gtk_window_set_title(GTK_WINDOW(mainwindow1), baseinputfilename);
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, baseinputfilename2);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- cnt = 1000;
- while (gtk_events_pending()) {
- cnt--;
- if (cnt > 0) {
- gtk_main_iteration();
- /* this updates the status text */
- }
- }
- #endif
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- cnt = 1000;
- while (gtk_main_iteration()) {
- cnt--;
- if (cnt > 0) {
- /* this should update the status text */ ;
- }
- }
- /* set sliders to defaults */
- zfactor = 1.0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale1), 50);
- vxmin = 0;
- vymin = 0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), 0);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), 0);
- /* filename is not saved */
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* filename is not saved */
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* set directory for file chooser */
- static void set_current_folder(GtkFileChooser * chooser, const char *name)
- {
- GtkWidget *dialog;
- GFile *file = g_file_new_for_path(name);
- if (file) {
- if (gtk_file_chooser_set_current_folder(chooser, file, NULL) == FALSE) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(chooser),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Could not set the folder to %s", name);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- }
- g_object_unref(file);
- }
- return;
- }
- /* parse the file */
- static void open1_response_cb_fn(char *inputfilename, char *binputfilename)
- {
- gzFile f; /* the zipped file stream */
- GtkWidget *dialog = NULL;
- /* binputfilename is the short filename and should not be numm */
- /* open file to parse */
- errno = 0;
- /* open zipped or unzipped file as file stream */
- f = gzopen(inputfilename, "rb");
- if (f == NULL || 0) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Cannot open file %s", inputfilename);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 1;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the dot data */
- if (dotparse(maingraph, f, inputfilename, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- fflush(stdout);
- gzclose(f);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- fflush(stdout);
- gzclose(f);
- /* set the basename of file as window title /tmp/foo.dot has window title foo.dot */
- if (binputfilename) {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), binputfilename);
- } else {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), inputfilename);
- }
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, inputfilename);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- /* set sliders to defaults */
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- return;
- }
- /* run dialog and set bool done to TRUE if ready */
- static void open1_response_cb(GtkDialog * dialog, int response_id, gpointer data)
- {
- gboolean *done = data; /* bool to set is passed on at call */
- GListModel *files = NULL;
- guint i = 0;
- guint n = 0;
- GFile *file = NULL;
- GFile *folder = NULL;
- char *uri = NULL;
- char *file_chooser_dir = NULL;
- char *inputfilename = NULL;
- char *file_chooser_filename = NULL;
- char *bname = NULL;
- if (response_id == GTK_RESPONSE_OK) {
- /* scan the list with selected files */
- files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog));
- n = g_list_model_get_n_items(files);
- if (yydebug || 0) {
- g_print("%s(): selected %d files\n", __func__, n);
- }
- for (i = 0; i < n; i++) {
- file = g_list_model_get_item(files, i);
- uri = g_file_get_uri(file);
- /* option here
- * the uri is like file:///bin/true
- * this allows for network uri
- * as https://graphviewer.nl/data/example.dot
- */
- if (uri == NULL) {
- g_print("%s(): file %d has nil name\n", __func__, i);
- } else {
- if (strlen(uri) == 0) {
- g_print("%s(): file %d has empty name \"\"\n", __func__, i);
- } else {
- if (i != 0) {
- g_print("%s(): skipped file %d with name %s\n", __func__, i, uri);
- } else {
- /* this is the first file to read
- * uri is file:///bin/foo
- * g_file_get_parse_name(file) is /bin/foo
- * g_file_get_basename(file) is foo
- * g_file_get_path(file) is /bin/foo
- */
- /* update directory of chosen file */
- folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (folder) {
- file_chooser_dir = g_file_get_parse_name(folder);
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- g_free(file_chooser_dir);
- file_chooser_dir = NULL;
- }
- g_object_unref(folder);
- }
- /* copy filename */
- file_chooser_filename = g_file_get_parse_name(file);
- if (file_chooser_filename) {
- if (strlen(file_chooser_filename)) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- } else {
- g_print("%s(): empty filename\n", __func__);
- }
- bname = g_file_get_basename(file);
- /* read and parse the file */
- open1_response_cb_fn(file_chooser_filename, bname);
- if (bname) {
- g_free(bname);
- bname = NULL;
- };
- /* there could have been a parse error */
- g_free(file_chooser_filename);
- file_chooser_filename = NULL;
- }
- /* print the derived filenames */
- if (yydebug || 0) {
- g_print("%s(): %s %s %s %s %s\n", __func__, g_file_get_parse_name(file),
- g_file_get_basename(file), uri, g_file_get_path(file), g_file_get_parse_name(folder));
- }
- }
- }
- g_free(uri);
- uri = NULL;
- }
- g_object_unref(file);
- }
- g_object_unref(files);
- } else {
- /* no file selected */
- if (yydebug || 0) {
- g_print("%s(): open dialog was closed\n", __func__);
- }
- }
- /* inicate this dialog is finished in passed on var */
- *done = TRUE;
- g_main_context_wakeup(NULL);
- return;
- }
- /* open dot file */
- static void open1_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- gboolean multiple = FALSE; /* if TRUE multiple files can be selected as extended feature */
- GtkWidget *dialog = NULL;
- GtkFileFilter *filter = NULL;
- gboolean done = FALSE; /* indicator dialog is finished */
- if (action) {
- }
- if (parameter) {
- }
- if (user_data) {
- }
- /* see the testcase in gtk-4 testfilechooser.c */
- dialog = g_object_new(GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_OPEN, "select-multiple", multiple, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Open dot graph file");
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), ("_Cancel"), GTK_RESPONSE_CANCEL, ("_Open"), GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- /* the callback will set bool done to TRUE if ready */
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(open1_response_cb), (gpointer) & done);
- /* Filters */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "All Files");
- gtk_file_filter_add_pattern(filter, "*");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "dot");
- gtk_file_filter_add_pattern(filter, "*.dot");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "gv");
- gtk_file_filter_add_pattern(filter, "*.gv");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- /* this are the gzipped graph files */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "dot.gz");
- gtk_file_filter_add_pattern(filter, "*.dot.gz");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "gv.gz");
- gtk_file_filter_add_pattern(filter, "*.gv.gz");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- if (lastopendir) {
- set_current_folder(GTK_FILE_CHOOSER(dialog), lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- /* run dialog and wait until it is ready */
- while (done == FALSE) {
- g_main_context_iteration(NULL, TRUE);
- }
- gtk_window_destroy(GTK_WINDOW(dialog));
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* 'open' in 'file' menu activated - sub menu in menu items in menu bar in vbox1 */
- static void on_top_level_window_open2_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *edialog = (GtkWidget *) 0;
- GtkWidget *pdialog = (GtkWidget *) 0;
- GtkWidget *dialog = (GtkWidget *) 0;
- char *file_chooser_filename = (char *)0;
- char *file_chooser_dir = (char *)0;
- GtkFileChooser *chooser = NULL;
- char *inputfilename = (char *)0;
- char *baseinputfilename = (char *)0;
- char *baseinputfilename2 = (char *)0;
- gzFile f = NULL;
- char *bname = NULL;
- int cnt = 0;
- if (menuitem) {
- }
- if (user_data) {
- }
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select DOT Graph File", 0, /* parent_window */
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select DOT Graph File", GTK_WINDOW(mainwindow1) /* parent_window */
- ,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
- #endif
- chooser = GTK_FILE_CHOOSER(dialog);
- /* use same dir if opened in earlier dir */
- if (lastopendir) {
- gtk_file_chooser_set_current_folder(chooser, lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- /* run the window to select a input file */
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- /* open button */
- file_chooser_filename = (char *)gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- file_chooser_dir = (char *)gtk_file_chooser_get_current_folder(chooser);
- } else {
- /* cancel button */
- (void)gtk_widget_destroy(dialog);
- return;
- }
- /* */
- (void)gtk_widget_destroy(dialog);
- /* update last-used-dir */
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_dir);
- }
- /* copy the input filename from gtk */
- if (file_chooser_filename) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_filename);
- } else {
- return;
- }
- /* set filename in window */
- bname = g_path_get_basename(inputfilename);
- baseinputfilename2 = dp_calloc(1, (strlen(bname) + 1));
- strcpy(baseinputfilename2, bname);
- /* not dp_free() because gtk allocated */
- g_free(bname);
- /* open file to parse */
- errno = 0;
- f = gzopen(inputfilename, "rb");
- if (f == NULL) {
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "Cannot open file %s for reading (%s)", inputfilename, g_strerror(errno));
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 1;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the dot data */
- if (dotparse(maingraph, f, baseinputfilename2, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- pdialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_dialog_run(GTK_DIALOG(pdialog));
- gtk_widget_destroy(pdialog);
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- fflush(stdout);
- gzclose(f);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- gzclose(f);
- bname = g_path_get_basename(inputfilename);
- baseinputfilename = uniqstr(bname);
- /* not dp_free() because gtk allocated */
- g_free(bname);
- gtk_window_set_title(GTK_WINDOW(mainwindow1), baseinputfilename);
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, baseinputfilename2);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- cnt = 1000;
- while (gtk_events_pending()) {
- cnt--;
- if (cnt > 0) {
- gtk_main_iteration();
- /* this updates the status text */
- }
- }
- #endif
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- cnt = 1000;
- while (gtk_main_iteration()) {
- cnt--;
- if (cnt > 0) {
- /* this should update the status text */ ;
- }
- }
- /* set sliders to defaults */
- zfactor = 1.0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale1), 50);
- vxmin = 0;
- vymin = 0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), 0);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), 0);
- /* filename is not saved */
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* filename is not saved */
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* parse the file */
- static void open3_response_cb_fn(char *inputfilename, char *binputfilename)
- {
- gzFile f; /* the zipped file stream */
- GtkWidget *dialog = NULL;
- /* binputfilename is the short filename and should not be numm */
- /* open file to parse */
- errno = 0;
- /* open zipped or unzipped file as file stream */
- f = gzopen(inputfilename, "rb");
- if (f == NULL || 0) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Cannot open file %s", inputfilename);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 1;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the dot data */
- if (vcgparse(maingraph, f, inputfilename, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- fflush(stdout);
- gzclose(f);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- fflush(stdout);
- gzclose(f);
- /* set the basename of file as window title /tmp/foo.dot has window title foo.dot */
- if (binputfilename) {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), binputfilename);
- } else {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), inputfilename);
- }
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, inputfilename);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- /* set sliders to defaults */
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- return;
- }
- /* run dialog and set bool done to TRUE if ready */
- static void open3_response_cb(GtkDialog * dialog, int response_id, gpointer data)
- {
- gboolean *done = data; /* bool to set is passed on at call */
- GListModel *files = NULL;
- guint i = 0;
- guint n = 0;
- GFile *file = NULL;
- GFile *folder = NULL;
- char *uri = NULL;
- char *file_chooser_dir = NULL;
- char *inputfilename = NULL;
- char *file_chooser_filename = NULL;
- char *bname = NULL;
- if (response_id == GTK_RESPONSE_OK) {
- /* scan the list with selected files */
- files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog));
- n = g_list_model_get_n_items(files);
- if (yydebug || 0) {
- g_print("%s(): selected %d files\n", __func__, n);
- }
- for (i = 0; i < n; i++) {
- file = g_list_model_get_item(files, i);
- uri = g_file_get_uri(file);
- /* option here
- * the uri is like file:///bin/true
- * this allows for network uri
- * as https://graphviewer.nl/data/example.dot
- */
- if (uri == NULL) {
- g_print("%s(): file %d has nil name\n", __func__, i);
- } else {
- if (strlen(uri) == 0) {
- g_print("%s(): file %d has empty name \"\"\n", __func__, i);
- } else {
- if (i != 0) {
- g_print("%s(): skipped file %d with name %s\n", __func__, i, uri);
- } else {
- /* this is the first file to read
- * uri is file:///bin/foo
- * g_file_get_parse_name(file) is /bin/foo
- * g_file_get_basename(file) is foo
- * g_file_get_path(file) is /bin/foo
- */
- /* update directory of chosen file */
- folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (folder) {
- file_chooser_dir = g_file_get_parse_name(folder);
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- g_free(file_chooser_dir);
- file_chooser_dir = NULL;
- }
- g_object_unref(folder);
- }
- /* copy filename */
- file_chooser_filename = g_file_get_parse_name(file);
- if (file_chooser_filename) {
- if (strlen(file_chooser_filename)) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- } else {
- g_print("%s(): empty filename\n", __func__);
- }
- bname = g_file_get_basename(file);
- /* read and parse the file */
- open3_response_cb_fn(file_chooser_filename, bname);
- if (bname) {
- g_free(bname);
- bname = NULL;
- };
- /* there could have been a parse error */
- g_free(file_chooser_filename);
- file_chooser_filename = NULL;
- }
- /* print the derived filenames */
- if (yydebug || 0) {
- g_print("%s(): %s %s %s %s %s\n", __func__, g_file_get_parse_name(file),
- g_file_get_basename(file), uri, g_file_get_path(file), g_file_get_parse_name(folder));
- }
- }
- }
- g_free(uri);
- uri = NULL;
- }
- g_object_unref(file);
- }
- g_object_unref(files);
- } else {
- /* no file selected */
- if (yydebug || 0) {
- g_print("%s(): open dialog was closed\n", __func__);
- }
- }
- /* inicate this dialog is finished in passed on var */
- *done = TRUE;
- g_main_context_wakeup(NULL);
- return;
- }
- /* open vcg file */
- static void open3_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- gboolean multiple = FALSE; /* if TRUE multiple files can be selected as extended feature */
- GtkWidget *dialog = NULL;
- GtkFileFilter *filter = NULL;
- gboolean done = FALSE; /* indicator dialog is finished */
- if (action) {
- }
- if (parameter) {
- }
- if (user_data) {
- }
- /* see the testcase in gtk-4 testfilechooser.c */
- dialog = g_object_new(GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_OPEN, "select-multiple", multiple, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Open ci graph file");
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), ("_Cancel"), GTK_RESPONSE_CANCEL, ("_Open"), GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- /* the callback will set bool done to TRUE if ready */
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(open3_response_cb), (gpointer) & done);
- /* Filters */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "All Files");
- gtk_file_filter_add_pattern(filter, "*");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "vcg");
- gtk_file_filter_add_pattern(filter, "*.vcg");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "ci");
- gtk_file_filter_add_pattern(filter, "*.ci");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- /* this are the gzipped graph files */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "vcg.gz");
- gtk_file_filter_add_pattern(filter, "*.vcg.gz");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- if (lastopendir) {
- set_current_folder(GTK_FILE_CHOOSER(dialog), lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- /* run dialog and wait until it is ready */
- while (done == FALSE) {
- g_main_context_iteration(NULL, TRUE);
- }
- gtk_window_destroy(GTK_WINDOW(dialog));
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* 'open' in 'file' menu activated - sub menu in menu items in menu bar in vbox1 */
- static void on_top_level_window_open3_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *edialog = (GtkWidget *) 0;
- GtkWidget *pdialog = (GtkWidget *) 0;
- GtkWidget *dialog = (GtkWidget *) 0;
- char *file_chooser_filename = (char *)0;
- char *file_chooser_dir = (char *)0;
- GtkFileChooser *chooser = NULL;
- char *inputfilename = (char *)0;
- char *baseinputfilename = (char *)0;
- char *baseinputfilename2 = (char *)0;
- gzFile fvcg = (gzFile) 0;
- char *bname = NULL;
- if (menuitem) {
- }
- if (user_data) {
- }
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select CI Graph File", 0, /* parent_window */
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select CI Graph File", GTK_WINDOW(mainwindow1) /* parent_window */
- ,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
- #endif
- chooser = GTK_FILE_CHOOSER(dialog);
- /* use same dir if opened in earlier dir */
- if (lastopendir) {
- gtk_file_chooser_set_current_folder(chooser, lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- /* run the window to select a input file */
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- /* open button */
- file_chooser_filename = (char *)gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- file_chooser_dir = (char *)gtk_file_chooser_get_current_folder(chooser);
- } else {
- /* cancel button */
- (void)gtk_widget_destroy(dialog);
- return;
- }
- /* */
- (void)gtk_widget_destroy(dialog);
- /* update last-used-dir */
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_dir);
- }
- /* copy the input filename from gtk */
- if (file_chooser_filename) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_filename);
- } else {
- return;
- }
- /* set filename in window */
- bname = g_path_get_basename(inputfilename);
- baseinputfilename2 = dp_calloc(1, (strlen(bname) + 1));
- strcpy(baseinputfilename2, bname);
- /* not dp_free() because gtk allocated */
- g_free(bname);
- /* open file to parse */
- errno = 0;
- fvcg = gzopen(inputfilename, "r");
- if (fvcg == (gzFile) 0) {
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "Cannot open file %s for reading (%s)", inputfilename, g_strerror(errno));
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 2;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the vcg data */
- if (vcgparse(maingraph, fvcg, baseinputfilename2, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- pdialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_dialog_run(GTK_DIALOG(pdialog));
- gtk_widget_destroy(pdialog);
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- fflush(stdout);
- gzclose(fvcg);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- gzclose(fvcg);
- bname = g_path_get_basename(inputfilename);
- baseinputfilename = uniqstr(bname);
- /* not dp_free because gtk allocated */
- g_free(bname);
- gtk_window_set_title(GTK_WINDOW(mainwindow1), baseinputfilename);
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, baseinputfilename2);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- while (gtk_events_pending()) {
- gtk_main_iteration();
- /* this updates the status text */
- }
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- while (gtk_main_iteration()) {
- /* this should update the status text */ ;
- }
- /* set sliders to defaults */
- zfactor = 1.0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale1), 50);
- vxmin = 0;
- vymin = 0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), 0);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), 0);
- /* filename is not saved */
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* filename is not saved */
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* parse the file */
- static void open4_response_cb_fn(char *inputfilename, char *binputfilename)
- {
- gzFile f; /* the zipped file stream */
- GtkWidget *dialog = NULL;
- /* binputfilename is the short filename and should not be numm */
- /* open file to parse */
- errno = 0;
- /* open zipped or unzipped file as file stream */
- f = gzopen(inputfilename, "rb");
- if (f == NULL || 0) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Cannot open file %s", inputfilename);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg */
- graphtype = 1;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the jgf data */
- if (jgfparse(maingraph, f, inputfilename, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- fflush(stdout);
- gzclose(f);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- fflush(stdout);
- gzclose(f);
- /* set the basename of file as window title /tmp/foo.dot has window title foo.dot */
- if (binputfilename) {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), binputfilename);
- } else {
- gtk_window_set_title(GTK_WINDOW(mainwindow1), inputfilename);
- }
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, inputfilename);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- /* set sliders to defaults */
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- return;
- }
- /* run dialog and set bool done to TRUE if ready */
- static void open4_response_cb(GtkDialog * dialog, int response_id, gpointer data)
- {
- gboolean *done = data; /* bool to set is passed on at call */
- GListModel *files = NULL;
- guint i = 0;
- guint n = 0;
- GFile *file = NULL;
- GFile *folder = NULL;
- char *uri = NULL;
- char *file_chooser_dir = NULL;
- char *inputfilename = NULL;
- char *file_chooser_filename = NULL;
- char *bname = NULL;
- if (response_id == GTK_RESPONSE_OK) {
- /* scan the list with selected files */
- files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog));
- n = g_list_model_get_n_items(files);
- if (yydebug || 0) {
- g_print("%s(): selected %d files\n", __func__, n);
- }
- for (i = 0; i < n; i++) {
- file = g_list_model_get_item(files, i);
- uri = g_file_get_uri(file);
- /* option here
- * the uri is like file:///bin/true
- * this allows for network uri
- * as https://graphviewer.nl/data/example.dot
- */
- if (uri == NULL) {
- g_print("%s(): file %d has nil name\n", __func__, i);
- } else {
- if (strlen(uri) == 0) {
- g_print("%s(): file %d has empty name \"\"\n", __func__, i);
- } else {
- if (i != 0) {
- g_print("%s(): skipped file %d with name %s\n", __func__, i, uri);
- } else {
- /* this is the first file to read
- * uri is file:///bin/foo
- * g_file_get_parse_name(file) is /bin/foo
- * g_file_get_basename(file) is foo
- * g_file_get_path(file) is /bin/foo
- */
- /* update directory of chosen file */
- folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (folder) {
- file_chooser_dir = g_file_get_parse_name(folder);
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- g_free(file_chooser_dir);
- file_chooser_dir = NULL;
- }
- g_object_unref(folder);
- }
- /* copy filename */
- file_chooser_filename = g_file_get_parse_name(file);
- if (file_chooser_filename) {
- if (strlen(file_chooser_filename)) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- } else {
- g_print("%s(): empty filename\n", __func__);
- }
- bname = g_file_get_basename(file);
- /* read and parse the file */
- open4_response_cb_fn(file_chooser_filename, bname);
- if (bname) {
- g_free(bname);
- bname = NULL;
- };
- /* there could have been a parse error */
- g_free(file_chooser_filename);
- file_chooser_filename = NULL;
- }
- /* print the derived filenames */
- if (yydebug || 0) {
- g_print("%s(): %s %s %s %s %s\n", __func__, g_file_get_parse_name(file),
- g_file_get_basename(file), uri, g_file_get_path(file), g_file_get_parse_name(folder));
- }
- }
- }
- g_free(uri);
- uri = NULL;
- }
- g_object_unref(file);
- }
- g_object_unref(files);
- } else {
- /* no file selected */
- if (yydebug || 0) {
- g_print("%s(): open dialog was closed\n", __func__);
- }
- }
- /* inicate this dialog is finished in passed on var */
- *done = TRUE;
- g_main_context_wakeup(NULL);
- return;
- }
- /* open jgf file */
- static void open4_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- gboolean multiple = FALSE; /* if TRUE multiple files can be selected as extended feature */
- GtkWidget *dialog = NULL;
- GtkFileFilter *filter = NULL;
- gboolean done = FALSE; /* indicator dialog is finished */
- if (action) {
- }
- if (parameter) {
- }
- if (user_data) {
- }
- /* see the testcase in gtk-4 testfilechooser.c */
- dialog = g_object_new(GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_OPEN, "select-multiple", multiple, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Open jgf graph file");
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), ("_Cancel"), GTK_RESPONSE_CANCEL, ("_Open"), GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- /* the callback will set bool done to TRUE if ready */
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(open4_response_cb), (gpointer) & done);
- /* Filters */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "All Files");
- gtk_file_filter_add_pattern(filter, "*");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "jgf");
- gtk_file_filter_add_pattern(filter, "*.jgf");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- /* this are the gzipped graph files */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "jgf.gz");
- gtk_file_filter_add_pattern(filter, "*.jgf.gz");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- if (lastopendir) {
- set_current_folder(GTK_FILE_CHOOSER(dialog), lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- /* run dialog and wait until it is ready */
- while (done == FALSE) {
- g_main_context_iteration(NULL, TRUE);
- }
- gtk_window_destroy(GTK_WINDOW(dialog));
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* 'open' in 'file' menu activated - sub menu in menu items in menu bar in vbox1 */
- static void on_top_level_window_open4_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *edialog = (GtkWidget *) 0;
- GtkWidget *pdialog = (GtkWidget *) 0;
- GtkWidget *dialog = (GtkWidget *) 0;
- char *file_chooser_filename = (char *)0;
- char *file_chooser_dir = (char *)0;
- GtkFileChooser *chooser = NULL;
- char *inputfilename = (char *)0;
- char *baseinputfilename = (char *)0;
- char *baseinputfilename2 = (char *)0;
- gzFile f = NULL;
- char *bname = NULL;
- if (menuitem) {
- }
- if (user_data) {
- }
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select JGF Graph File", 0, /* parent_window */
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- /* see gimp source code howto */
- dialog = gtk_file_chooser_dialog_new("Select JGF Graph File", GTK_WINDOW(mainwindow1) /* parent_window */
- ,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
- #endif
- chooser = GTK_FILE_CHOOSER(dialog);
- /* use same dir if opened in earlier dir */
- if (lastopendir) {
- gtk_file_chooser_set_current_folder(chooser, lastopendir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- /* run the window to select a input file */
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- /* open button */
- file_chooser_filename = (char *)gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- file_chooser_dir = (char *)gtk_file_chooser_get_current_folder(chooser);
- } else {
- /* cancel button */
- (void)gtk_widget_destroy(dialog);
- return;
- }
- /* */
- (void)gtk_widget_destroy(dialog);
- /* update last-used-dir */
- if (file_chooser_dir) {
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- lastopendir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastopendir, file_chooser_dir);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_dir);
- }
- /* copy the input filename from gtk */
- if (file_chooser_filename) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- /* node dp_free() because gtk allocated */
- g_free(file_chooser_filename);
- } else {
- return;
- }
- /* set filename in window */
- bname = g_path_get_basename(inputfilename);
- baseinputfilename2 = dp_calloc(1, (strlen(bname) + 1));
- strcpy(baseinputfilename2, bname);
- /* not dp_free() because gtk allocated */
- g_free(bname);
- /* open file to parse */
- errno = 0;
- f = gzopen(inputfilename, "rb");
- if (f == NULL) {
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "Cannot open file %s for reading (%s)", inputfilename, g_strerror(errno));
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* data is unchanged, so keep validdata status */
- return;
- }
- /* type of graph data 0=gml 1=dot 2=vcg 3=jgf */
- graphtype = 3;
- do_clear_all(0);
- /* background r/g/b of drawing */
- bgcr = 0xff;
- bgcg = 0xff;
- bgcb = 0xff;
- /* create root graph */
- create_maingraph();
- /* parse the vcg data */
- if (jgfparse(maingraph, f, baseinputfilename2, argv0)) {
- /* parse error */
- if (strlen(parsermessage) == 0) {
- strcpy(parsermessage, "no parser message");
- }
- pdialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", parsermessage);
- gtk_dialog_run(GTK_DIALOG(pdialog));
- gtk_widget_destroy(pdialog);
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- fflush(stdout);
- gzclose(f);
- /* data is invalid at this point */
- validdata = 0;
- do_clear_all(0);
- /* use package string program name as set by configure in config.h */
- gtk_window_set_title(GTK_WINDOW(mainwindow1), PACKAGE_STRING);
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- gzclose(f);
- bname = g_path_get_basename(inputfilename);
- baseinputfilename = uniqstr(bname);
- /* not dp_free() because gtk allocated */
- g_free(bname);
- gtk_window_set_title(GTK_WINDOW(mainwindow1), baseinputfilename);
- /* check for empty graph here */
- if (maingraph->rawnodelist) {
- printf("%s(): calculating layout of file %s\n", __func__, baseinputfilename2);
- fflush(stdout);
- /* update status text */
- update_status_text("Wait ... Calculating Layout");
- while (gtk_events_pending()) {
- gtk_main_iteration();
- /* this updates the status text */
- }
- do_layout_all(maingraph);
- fflush(stdout);
- /* update status text */
- update_status_text(NULL);
- while (gtk_main_iteration()) {
- /* this should update the status text */ ;
- }
- /* set sliders to defaults */
- zfactor = 1.0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale1), 50);
- vxmin = 0;
- vymin = 0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), 0);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), 0);
- /* fit drawing in window */
- dofit();
- validdata = 1;
- } else {
- /* update status text */
- update_status_text("Empty graph ... No Nodes");
- validdata = 0;
- }
- inputfilename = dp_free(inputfilename);
- if (inputfilename) {
- }
- baseinputfilename2 = dp_free(baseinputfilename2);
- if (baseinputfilename2) {
- }
- /* re draw screen */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* generate the file */
- static void save1_response_cb_fn(char *svgfilename, char *binputfilename)
- {
- int mymaxx = 0;
- int mymaxy = 0;
- int saved_vxmin = 0;
- int saved_vymin = 0;
- FILE *fstream = NULL;
- GtkWidget *dialog = NULL;
- cairo_surface_t *surface = NULL;
- cairo_t *crp = NULL;
- if (binputfilename) {
- }
- errno = 0;
- fstream = fopen(svgfilename, "wb");
- /* check if open */
- if (fstream == NULL) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Cannot open file %s", svgfilename);
- gtk_widget_show(GTK_WIDGET(dialog));
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- return;
- }
- /* write the svg image data */
- /* save current gui settings */
- saved_vxmin = vxmin;
- saved_vymin = vymin;
- /* output whole drawing with a small border, then edge line at end is in drawing */
- vxmin = 0;
- vymin = 0;
- mymaxx = (int)((maxx + xspacing) * /* 1.0 */ zfactor);
- mymaxy = (int)((maxy + yspacing) * /* 1.0 */ zfactor);
- surface = cairo_svg_surface_create(svgfilename, mymaxx, mymaxy);
- /* */
- crp = cairo_create(surface);
- /* fill drawing background with background color */
- cairo_set_source_rgb(crp, bgcr / 255.0, bgcg / 255.0, bgcb / 255.0);
- /* select whole drawing to fill wth background color */
- cairo_rectangle(crp, 0, 0, mymaxx, mymaxy);
- cairo_fill(crp);
- /* use zoom slider drawing scale */
- cairo_scale(crp, /*1.0 */ zfactor, /*1.0 */ zfactor);
- on_top_level_window_drawingarea1_expose_event_edges(crp);
- on_top_level_window_drawingarea1_expose_event_nodes(crp);
- cairo_destroy(crp);
- cairo_surface_destroy(surface);
- /* restore screen (x,y) min */
- vxmin = saved_vxmin;
- vymin = saved_vymin;
- fclose(fstream);
- return;
- }
- /* run dialog and set bool done to TRUE if ready */
- static void save1_response_cb(GtkDialog * dialog, int response_id, gpointer data)
- {
- gboolean *done = data; /* bool to set is passed on at call */
- GListModel *files = NULL;
- guint i = 0;
- guint n = 0;
- GFile *file = NULL;
- GFile *folder = NULL;
- char *uri = NULL;
- char *file_chooser_dir = NULL;
- char *inputfilename = NULL;
- char *file_chooser_filename = NULL;
- char *bbbname = NULL;
- /* this allows to select multiple files at once and generate all output files with same data */
- /* the uri allow to save to url as on used the internet */
- if (response_id == GTK_RESPONSE_OK && 1 /* for testing */ ) {
- /* scan the list with selected files */
- files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog));
- n = g_list_model_get_n_items(files);
- /* this causes crash only at save at the free */
- for (i = 0; i < n; i++) {
- file = g_list_model_get_item(files, i);
- uri = g_file_get_uri(file);
- /* option here
- * the uri is like file:///bin/true
- * this allows for network uri
- * as https://graphviewer.nl/data/example.dot
- */
- if (uri == NULL) {
- g_print("%s(): file %d has nil name\n", __func__, i);
- } else {
- if (strlen(uri) == 0) {
- g_print("%s(): file %d has empty name \"\"\n", __func__, i);
- } else {
- if (i != 0) {
- g_print("%s(): skipped file %d with name %s\n", __func__, i, uri);
- } else {
- if (yydebug || 0) {
- g_print("%s(): selected file %d with name %s\n", __func__, i, uri);
- }
- /* this is the first file to read
- * uri is file:///bin/foo
- * g_file_get_parse_name(file) is /bin/foo
- * g_file_get_basename(file) is foo
- * g_file_get_path(file) is /bin/foo
- */
- /* update directory of chosen file */
- folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (folder) {
- file_chooser_dir = g_file_get_parse_name(folder);
- if (file_chooser_dir) {
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- lastsavedir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastsavedir, file_chooser_dir);
- g_free(file_chooser_dir);
- file_chooser_dir = NULL;
- }
- g_object_unref(folder);
- }
- /* copy filename */
- file_chooser_filename = g_file_get_parse_name(file);
- if (file_chooser_filename) {
- if (strlen(file_chooser_filename)) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- bbbname = g_file_get_basename(file);
- /* write the file */
- save1_response_cb_fn(file_chooser_filename, bbbname);
- if (bbbname) {
- g_free(bbbname);
- bbbname = NULL;
- }
- } else {
- g_print("%s(): empty filename\n", __func__);
- }
- /* there could have been a error */
- g_free(file_chooser_filename);
- file_chooser_filename = NULL;
- }
- /* print the derived filenames */
- if (yydebug || 0) {
- g_print("%s(): %s %s %s %s %s\n", __func__, g_file_get_parse_name(file),
- g_file_get_basename(file), uri, g_file_get_path(file), g_file_get_parse_name(folder));
- }
- }
- }
- g_free(uri);
- uri = NULL;
- }
- g_object_unref(file);
- }
- g_object_unref(files);
- } else {
- /* no file selected */
- if (yydebug || 0) {
- g_print("%s(): save dialog was closed\n", __func__);
- }
- }
- /* inicate this dialog is finished in passed on var */
- *done = TRUE;
- g_main_context_wakeup(NULL);
- return;
- }
- /* save svg */
- static void save1_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- gboolean multiple = FALSE; /* if TRUE multiple files can be selected as extended feature */
- GtkWidget *dialog = NULL;
- GtkFileFilter *filter = NULL;
- gboolean done = FALSE; /* indicator dialog is finished */
- if (action) {
- }
- if (parameter) {
- }
- if (user_data) {
- }
- /* nothing todo if there is no layout */
- if (validdata == 0) {
- return;
- }
- /* see the testcase in gtk-4 testfilechooser.c */
- dialog = g_object_new(GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_SAVE, "select-multiple", multiple, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Save svg file");
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), ("_Cancel"), GTK_RESPONSE_CANCEL, ("_Save"), GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- /* the callback will set bool done to TRUE if ready */
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(save1_response_cb), (gpointer) & done);
- /* Filters */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "All Files");
- gtk_file_filter_add_pattern(filter, "*");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "svg");
- gtk_file_filter_add_pattern(filter, "*.svg");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- if (lastsavedir) {
- set_current_folder(GTK_FILE_CHOOSER(dialog), lastsavedir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- /* run dialog and wait until it is ready */
- while (done == FALSE) {
- g_main_context_iteration(NULL, TRUE);
- }
- gtk_window_destroy(GTK_WINDOW(dialog));
- dialog = NULL;
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* save as gtk svg */
- static void on_top_level_window_svg1_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *dialog = (GtkWidget *) 0;
- GtkWidget *edialog = (GtkWidget *) 0;
- char *file_chooser_filename = (char *)0;
- char *file_chooser_dir = (char *)0;
- GtkFileChooser *chooser = NULL;
- GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
- gint res = 0;
- char *svgfilename = NULL;
- FILE *fstream = NULL;
- int mymaxx = 0;
- int mymaxy = 0;
- int saved_vxmin = 0;
- int saved_vymin = 0;
- cairo_surface_t *surface = NULL;
- cairo_t *crp = NULL;
- /* nothing todo if there is no layout */
- if (validdata == 0) {
- return;
- }
- if (menuitem) {
- }
- if (user_data) {
- }
- dialog = gtk_file_chooser_dialog_new("Save As SVG Image",
- /* parent_window */ NULL,
- action, "_Cancel", GTK_RESPONSE_CANCEL, "_Save", GTK_RESPONSE_ACCEPT, NULL);
- chooser = GTK_FILE_CHOOSER(dialog);
- /* change to last used dir if any */
- if (lastsavedir) {
- gtk_file_chooser_set_current_folder(chooser, lastsavedir);
- }
- /* ask to override existing */
- gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE);
- /* get the filename */
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- res = gtk_dialog_run(GTK_DIALOG(dialog));
- if (res == GTK_RESPONSE_ACCEPT) {
- file_chooser_filename = gtk_file_chooser_get_filename(chooser);
- file_chooser_dir = gtk_file_chooser_get_current_folder(chooser);
- } else {
- /* cancel button */
- (void)gtk_widget_destroy(dialog);
- return;
- }
- /* update last-used-dir */
- if (file_chooser_dir) {
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- lastsavedir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastsavedir, file_chooser_dir);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_dir);
- }
- /* */
- (void)gtk_widget_destroy(dialog);
- /* */
- if (file_chooser_filename) {
- svgfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(svgfilename, file_chooser_filename);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_filename);
- } else {
- /* no filename */
- return;
- }
- errno = 0;
- fstream = fopen(svgfilename, "wb");
- /* check if open */
- if (fstream == NULL) {
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE, "Cannot open file %s for writing (%s)", svgfilename, g_strerror(errno));
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- svgfilename = dp_free(svgfilename);
- if (svgfilename) {
- }
- return;
- }
- /* write the svg image data */
- /* save current gui settings */
- saved_vxmin = vxmin;
- saved_vymin = vymin;
- /* output whole drawing with a small border, then edge line at end is in drawing */
- vxmin = 0;
- vymin = 0;
- mymaxx = (int)((maxx + xspacing) * /* 1.0 */ zfactor);
- mymaxy = (int)((maxy + yspacing) * /* 1.0 */ zfactor);
- surface = cairo_svg_surface_create(svgfilename, mymaxx, mymaxy);
- /* */
- crp = cairo_create(surface);
- /* fill drawing background with background color */
- cairo_set_source_rgb(crp, bgcr / 255.0, bgcg / 255.0, bgcb / 255.0);
- /* select whole drawing to fill wth background color */
- cairo_rectangle(crp, 0, 0, mymaxx, mymaxy);
- cairo_fill(crp);
- /* use zoom slider drawing scale */
- cairo_scale(crp, /*1.0 */ zfactor, /*1.0 */ zfactor);
- on_top_level_window_drawingarea1_expose_event_edges(crp);
- on_top_level_window_drawingarea1_expose_event_nodes(crp);
- cairo_destroy(crp);
- cairo_surface_destroy(surface);
- /* restore screen (x,y) min */
- vxmin = saved_vxmin;
- vymin = saved_vymin;
- fclose(fstream);
- svgfilename = dp_free(svgfilename);
- if (svgfilename) {
- }
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* generate the file */
- static void save2_response_cb_fn(char *diafilename, char *binputfilename)
- {
- FILE *fstream = NULL;
- GtkWidget *dialog = NULL;
- if (binputfilename) {
- }
- errno = 0;
- fstream = fopen(diafilename, "wb");
- /* check if open */
- if (fstream == NULL) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Cannot open file %s", diafilename);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- return;
- }
- /* write the dia diagram */
- graph2dia(maingraph, fstream);
- fclose(fstream);
- return;
- }
- /* run dialog and set bool done to TRUE if ready */
- static void save2_response_cb(GtkDialog * dialog, int response_id, gpointer data)
- {
- gboolean *done = data; /* bool to set is passed on at call */
- GListModel *files = NULL;
- guint i = 0;
- guint n = 0;
- GFile *file = NULL;
- GFile *folder = NULL;
- char *uri = NULL;
- char *file_chooser_dir = NULL;
- char *inputfilename = NULL;
- char *file_chooser_filename = NULL;
- char *bbbname = NULL;
- /* this allows to select multiple files at once and generate all output files with same data */
- /* the uri allow to save to url as on used the internet */
- if (response_id == GTK_RESPONSE_OK && 1 /* for testing */ ) {
- /* scan the list with selected files */
- files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog));
- n = g_list_model_get_n_items(files);
- /* this causes crash only at save at the free */
- for (i = 0; i < n; i++) {
- file = g_list_model_get_item(files, i);
- uri = g_file_get_uri(file);
- /* option here
- * the uri is like file:///bin/true
- * this allows for network uri
- * as https://graphviewer.nl/data/example.dot
- */
- if (uri == NULL) {
- g_print("%s(): file %d has nil name\n", __func__, i);
- } else {
- if (strlen(uri) == 0) {
- g_print("%s(): file %d has empty name \"\"\n", __func__, i);
- } else {
- if (i != 0) {
- g_print("%s(): skipped file %d with name %s\n", __func__, i, uri);
- } else {
- if (yydebug || 0) {
- g_print("%s(): selected file %d with name %s\n", __func__, i, uri);
- }
- /* this is the first file to read
- * uri is file:///bin/foo
- * g_file_get_parse_name(file) is /bin/foo
- * g_file_get_basename(file) is foo
- * g_file_get_path(file) is /bin/foo
- */
- /* update directory of chosen file */
- folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (folder) {
- file_chooser_dir = g_file_get_parse_name(folder);
- if (file_chooser_dir) {
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- lastsavedir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastsavedir, file_chooser_dir);
- g_free(file_chooser_dir);
- file_chooser_dir = NULL;
- }
- g_object_unref(folder);
- }
- /* copy filename */
- file_chooser_filename = g_file_get_parse_name(file);
- if (file_chooser_filename) {
- if (strlen(file_chooser_filename)) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- bbbname = g_file_get_basename(file);
- /* write the file */
- save2_response_cb_fn(file_chooser_filename, bbbname);
- if (bbbname) {
- g_free(bbbname);
- bbbname = NULL;
- }
- } else {
- g_print("%s(): empty filename\n", __func__);
- }
- /* there could have been a error */
- g_free(file_chooser_filename);
- file_chooser_filename = NULL;
- }
- /* print the derived filenames */
- if (yydebug || 0) {
- g_print("%s(): %s %s %s %s %s\n", __func__, g_file_get_parse_name(file),
- g_file_get_basename(file), uri, g_file_get_path(file), g_file_get_parse_name(folder));
- }
- }
- }
- g_free(uri);
- uri = NULL;
- }
- g_object_unref(file);
- }
- g_object_unref(files);
- } else {
- /* no file selected */
- if (yydebug || 0) {
- g_print("%s(): save dialog was closed\n", __func__);
- }
- }
- /* inicate this dialog is finished in passed on var */
- *done = TRUE;
- g_main_context_wakeup(NULL);
- return;
- }
- /* save dia xml */
- static void save2_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- gboolean multiple = FALSE; /* if TRUE multiple files can be selected as extended feature */
- GtkWidget *dialog = NULL;
- GtkFileFilter *filter = NULL;
- gboolean done = FALSE; /* indicator dialog is finished */
- if (action) {
- }
- if (parameter) {
- }
- if (user_data) {
- }
- /* nothing todo if there is no layout */
- if (validdata == 0) {
- return;
- }
- /* see the testcase in gtk-4 testfilechooser.c */
- dialog = g_object_new(GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_SAVE, "select-multiple", multiple, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Save dia xml file");
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), ("_Cancel"), GTK_RESPONSE_CANCEL, ("_Save"), GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- /* the callback will set bool done to TRUE if ready */
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(save2_response_cb), (gpointer) & done);
- /* Filters */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "All Files");
- gtk_file_filter_add_pattern(filter, "*");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "dia");
- gtk_file_filter_add_pattern(filter, "*.dia");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- if (lastsavedir) {
- set_current_folder(GTK_FILE_CHOOSER(dialog), lastsavedir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- /* run dialog and wait until it is ready */
- while (done == FALSE) {
- g_main_context_iteration(NULL, TRUE);
- }
- gtk_window_destroy(GTK_WINDOW(dialog));
- dialog = NULL;
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* save as dia xml diagram */
- static void on_top_level_window_dia1_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *dialog = (GtkWidget *) 0;
- GtkWidget *edialog = (GtkWidget *) 0;
- char *file_chooser_filename = (char *)0;
- char *file_chooser_dir = (char *)0;
- GtkFileChooser *chooser = NULL;
- GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
- gint res = 0;
- char *diafilename = NULL;
- FILE *fstream = NULL;
- if (validdata == 0) {
- return;
- }
- if (menuitem) {
- }
- if (user_data) {
- }
- dialog = gtk_file_chooser_dialog_new("Save As DIA diagram",
- /* parent_window */ NULL,
- action, "_Cancel", GTK_RESPONSE_CANCEL, "_Save", GTK_RESPONSE_ACCEPT, NULL);
- chooser = GTK_FILE_CHOOSER(dialog);
- /* change to last used dir if any */
- if (lastsavedir) {
- gtk_file_chooser_set_current_folder(chooser, lastsavedir);
- }
- /* ask to override existing */
- gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE);
- /* get the filename */
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- res = gtk_dialog_run(GTK_DIALOG(dialog));
- if (res == GTK_RESPONSE_ACCEPT) {
- file_chooser_filename = gtk_file_chooser_get_filename(chooser);
- file_chooser_dir = gtk_file_chooser_get_current_folder(chooser);
- } else {
- /* cancel button */
- (void)gtk_widget_destroy(dialog);
- return;
- }
- /* update last-used-dir */
- if (file_chooser_dir) {
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- lastsavedir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastsavedir, file_chooser_dir);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_dir);
- }
- /* */
- (void)gtk_widget_destroy(dialog);
- /* */
- if (file_chooser_filename) {
- diafilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(diafilename, file_chooser_filename);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_filename);
- } else {
- /* no filename */
- return;
- }
- errno = 0;
- fstream = fopen(diafilename, "wb");
- /* check if open */
- if (fstream == NULL) {
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE, "Cannot open file %s for writing (%s)", diafilename, g_strerror(errno));
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- diafilename = dp_free(diafilename);
- if (diafilename) {
- }
- return;
- }
- /* write the dia diagram */
- graph2dia(maingraph, fstream);
- fclose(fstream);
- diafilename = dp_free(diafilename);
- if (diafilename) {
- }
- return;
- }
- #endif
- /* save as jgf json diagram json jgf version 2.1
- {
- "$schema": "http://json-schema.org/draft-07/schema#",
- "$id": "http://jsongraphformat.info/v2.1/json-graph-schema.json",
- "title": "JSON Graph Schema",
- "oneOf": [
- {
- "type": "object",
- "properties": {
- "graph": { "$ref": "#/definitions/graph" }
- },
- "additionalProperties": false,
- "required": [
- "graph"
- ]
- },
- {
- "type": "object",
- "properties": {
- "graphs": {
- "type": "array",
- "items": { "$ref": "#/definitions/graph" }
- }
- },
- "additionalProperties": false
- }
- ],
- "definitions": {
- "graph": {
- "oneOf": [
- {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "id": { "type": "string" },
- "label": { "type": "string" },
- "directed": { "type": [ "boolean" ], "default": true },
- "type": { "type": "string" },
- "metadata": { "type": [ "object" ] },
- "nodes": {
- "type": "object",
- "additionalProperties": { "$ref": "#/definitions/node" }
- },
- "edges": {
- "type": [ "array" ],
- "items": { "$ref": "#/definitions/edge" }
- }
- }
- },
- {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "id": { "type": "string" },
- "label": { "type": "string" },
- "directed": { "type": [ "boolean" ], "default": true },
- "type": { "type": "string" },
- "metadata": { "type": [ "object" ] },
- "nodes": {
- "type": "object",
- "additionalProperties": { "$ref": "#/definitions/node" }
- },
- "hyperedges": {
- "type": [ "array" ],
- "items": { "$ref": "#/definitions/directedhyperedge" }
- }
- }
- },
- {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "id": { "type": "string" },
- "label": { "type": "string" },
- "directed": { "type": [ "boolean" ], "enum": [false] },
- "type": { "type": "string" },
- "metadata": { "type": [ "object" ] },
- "nodes": {
- "type": "object",
- "additionalProperties": { "$ref": "#/definitions/node" }
- },
- "hyperedges": {
- "type": [ "array" ],
- "items": { "$ref": "#/definitions/undirectedhyperedge" }
- }
- },
- "required": [ "directed" ]
- }
- ]
- },
- "node": {
- "type": "object",
- "properties": {
- "label": { "type": "string" },
- "metadata": { "type": "object" },
- "additionalProperties": false
- }
- },
- "edge": {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "id": { "type": "string" },
- "source": { "type": "string" },
- "target": { "type": "string" },
- "relation": { "type": "string" },
- "directed": { "type": [ "boolean" ], "default": true },
- "label": { "type": "string" },
- "metadata": { "type": [ "object" ] }
- },
- "required": [ "source", "target" ]
- },
- "directedhyperedge": {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "id": { "type": "string" },
- "source": { "type": "array", "items": { "type": "string" } },
- "target": { "type": "array", "items": { "type": "string" } },
- "relation": { "type": "string" },
- "label": { "type": "string" },
- "metadata": { "type": [ "object" ] }
- },
- "required": [ "source", "target" ]
- },
- "undirectedhyperedge": {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "id": { "type": "string" },
- "nodes": { "type": "array", "items": { "type": "string" } },
- "relation": { "type": "string" },
- "label": { "type": "string" },
- "metadata": { "type": [ "object" ] }
- },
- "required": [ "nodes" ]
- }
- }
- }
- */
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* generate the file */
- static void save3_response_cb_fn(char *jgffilename, char *binputfilename)
- {
- FILE *fstream = NULL;
- GtkWidget *dialog = NULL;
- if (binputfilename) {
- }
- errno = 0;
- fstream = fopen(jgffilename, "wb");
- /* check if open */
- if (fstream == NULL) {
- dialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Cannot open file %s", jgffilename);
- gtk_widget_show(dialog);
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_window_destroy), NULL);
- return;
- }
- /* write the jgf json */
- graph2jgf(maingraph, fstream);
- fclose(fstream);
- return;
- }
- /* run dialog and set bool done to TRUE if ready */
- static void save3_response_cb(GtkDialog * dialog, int response_id, gpointer data)
- {
- gboolean *done = data; /* bool to set is passed on at call */
- GListModel *files = NULL;
- guint i = 0;
- guint n = 0;
- GFile *file = NULL;
- GFile *folder = NULL;
- char *uri = NULL;
- char *file_chooser_dir = NULL;
- char *inputfilename = NULL;
- char *file_chooser_filename = NULL;
- char *bbbname = NULL;
- /* this allows to select multiple files at once and generate all output files with same data */
- /* the uri allow to save to url as on used the internet */
- if (response_id == GTK_RESPONSE_OK && 1 /* for testing */ ) {
- /* scan the list with selected files */
- files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog));
- n = g_list_model_get_n_items(files);
- /* this causes crash only at save at the free */
- for (i = 0; i < n; i++) {
- file = g_list_model_get_item(files, i);
- uri = g_file_get_uri(file);
- /* option here
- * the uri is like file:///bin/true
- * this allows for network uri
- * as https://graphviewer.nl/data/example.dot
- */
- if (uri == NULL) {
- g_print("%s(): file %d has nil name\n", __func__, i);
- } else {
- if (strlen(uri) == 0) {
- g_print("%s(): file %d has empty name \"\"\n", __func__, i);
- } else {
- if (i != 0) {
- g_print("%s(): skipped file %d with name %s\n", __func__, i, uri);
- } else {
- if (yydebug || 0) {
- g_print("%s(): selected file %d with name %s\n", __func__, i, uri);
- }
- /* this is the first file to read
- * uri is file:///bin/foo
- * g_file_get_parse_name(file) is /bin/foo
- * g_file_get_basename(file) is foo
- * g_file_get_path(file) is /bin/foo
- */
- /* update directory of chosen file */
- folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (folder) {
- file_chooser_dir = g_file_get_parse_name(folder);
- if (file_chooser_dir) {
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- lastsavedir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastsavedir, file_chooser_dir);
- g_free(file_chooser_dir);
- file_chooser_dir = NULL;
- }
- g_object_unref(folder);
- }
- /* copy filename */
- file_chooser_filename = g_file_get_parse_name(file);
- if (file_chooser_filename) {
- if (strlen(file_chooser_filename)) {
- inputfilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(inputfilename, file_chooser_filename);
- bbbname = g_file_get_basename(file);
- /* write the file */
- save3_response_cb_fn(file_chooser_filename, bbbname);
- if (bbbname) {
- g_free(bbbname);
- bbbname = NULL;
- }
- } else {
- g_print("%s(): empty filename\n", __func__);
- }
- /* there could have been a error */
- g_free(file_chooser_filename);
- file_chooser_filename = NULL;
- }
- /* print the derived filenames */
- if (yydebug || 0) {
- g_print("%s(): %s %s %s %s %s\n", __func__, g_file_get_parse_name(file),
- g_file_get_basename(file), uri, g_file_get_path(file), g_file_get_parse_name(folder));
- }
- }
- }
- g_free(uri);
- uri = NULL;
- }
- g_object_unref(file);
- }
- g_object_unref(files);
- } else {
- /* no file selected */
- if (yydebug || 0) {
- g_print("%s(): save dialog was closed\n", __func__);
- }
- }
- /* inicate this dialog is finished in passed on var */
- *done = TRUE;
- g_main_context_wakeup(NULL);
- return;
- }
- /* save json jgf */
- static void save3_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- gboolean multiple = FALSE; /* if TRUE multiple files can be selected as extended feature */
- GtkWidget *dialog = NULL;
- GtkFileFilter *filter = NULL;
- gboolean done = FALSE; /* indicator dialog is finished */
- if (action) {
- }
- if (parameter) {
- }
- if (user_data) {
- }
- /* nothing todo if there is no layout */
- if (validdata == 0) {
- return;
- }
- /* see the testcase in gtk-4 testfilechooser.c */
- dialog = g_object_new(GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_SAVE, "select-multiple", multiple, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Save json jgf file");
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), ("_Cancel"), GTK_RESPONSE_CANCEL, ("_Save"), GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- /* the callback will set bool done to TRUE if ready */
- g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(save3_response_cb), (gpointer) & done);
- /* Filters */
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "All Files");
- gtk_file_filter_add_pattern(filter, "*");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "jgf");
- gtk_file_filter_add_pattern(filter, "*.jgf");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "json");
- gtk_file_filter_add_pattern(filter, "*.json");
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
- if (lastsavedir) {
- set_current_folder(GTK_FILE_CHOOSER(dialog), lastsavedir);
- }
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- /* run dialog and wait until it is ready */
- while (done == FALSE) {
- g_main_context_iteration(NULL, TRUE);
- }
- gtk_window_destroy(GTK_WINDOW(dialog));
- dialog = NULL;
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- static void on_top_level_window_jgf1_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- GtkWidget *dialog = (GtkWidget *) 0;
- GtkWidget *edialog = (GtkWidget *) 0;
- char *file_chooser_filename = (char *)0;
- char *file_chooser_dir = (char *)0;
- GtkFileChooser *chooser = NULL;
- GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
- gint res = 0;
- char *jgffilename = NULL;
- FILE *fstream = NULL;
- if (validdata == 0) {
- return;
- }
- if (menuitem) {
- }
- if (user_data) {
- }
- dialog = gtk_file_chooser_dialog_new("Save As JGF json",
- /* parent_window */ NULL,
- action, "_Cancel", GTK_RESPONSE_CANCEL, "_Save", GTK_RESPONSE_ACCEPT, NULL);
- chooser = GTK_FILE_CHOOSER(dialog);
- /* change to last used dir if any */
- if (lastsavedir) {
- gtk_file_chooser_set_current_folder(chooser, lastsavedir);
- }
- /* ask to override existing */
- gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE);
- /* get the filename */
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- res = gtk_dialog_run(GTK_DIALOG(dialog));
- if (res == GTK_RESPONSE_ACCEPT) {
- file_chooser_filename = gtk_file_chooser_get_filename(chooser);
- file_chooser_dir = gtk_file_chooser_get_current_folder(chooser);
- } else {
- /* cancel button */
- (void)gtk_widget_destroy(dialog);
- return;
- }
- /* update last-used-dir */
- if (file_chooser_dir) {
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- lastsavedir = dp_calloc(1, (strlen(file_chooser_dir) + 1));
- strcpy(lastsavedir, file_chooser_dir);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_dir);
- }
- /* */
- (void)gtk_widget_destroy(dialog);
- /* */
- if (file_chooser_filename) {
- jgffilename = dp_calloc(1, (strlen(file_chooser_filename) + 1));
- strcpy(jgffilename, file_chooser_filename);
- /* not dp_free() because gtk allocated */
- g_free(file_chooser_filename);
- } else {
- /* no filename */
- return;
- }
- errno = 0;
- fstream = fopen(jgffilename, "wb");
- /* check if open */
- if (fstream == NULL) {
- edialog = gtk_message_dialog_new(GTK_WINDOW(mainwindow1),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE, "Cannot open file %s for writing (%s)", jgffilename, g_strerror(errno));
- gtk_dialog_run(GTK_DIALOG(edialog));
- gtk_widget_destroy(edialog);
- jgffilename = dp_free(jgffilename);
- if (jgffilename) {
- }
- return;
- }
- /* write the jgf json */
- graph2jgf(maingraph, fstream);
- fclose(fstream);
- jgffilename = dp_free(jgffilename);
- if (jgffilename) {
- }
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- static void on_top_level_window_quit1_activate(GSimpleAction * action, GVariant * parameter, gpointer user_data)
- {
- if (action) {
- }
- if (parameter) {
- }
- do_clear_all(0);
- if (lastopendir) {
- lastopendir = dp_free(lastopendir);
- if (lastopendir) {
- }
- }
- if (lastsavedir) {
- lastsavedir = dp_free(lastsavedir);
- if (lastsavedir) {
- }
- }
- g_application_quit(G_APPLICATION(user_data));
- /* never reached */
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* 'quit' in 'file' menu activated - sub menu in menu items in menu bar in vbox1 */
- static void on_top_level_window_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
- {
- if (menuitem) {
- }
- if (user_data) {
- }
- top_level_window_main_quit();
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* left slider zoom scale */
- static void on_vscale1_changed(GtkAdjustment * adj, gpointer data)
- {
- gdouble val0 = 0.0;
- int val1 = 0;
- if (data) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- val0 = gtk_adjustment_get_value(adj);
- val1 = (int)val0;
- zfactor = exp((double)(3 * (val1 - 50)) / (double)50);
- if (option_gdebug > 1 || 0) {
- printf("%s(): zoomslider=%d zoomfactor=%f\n", __func__, val1, zfactor);
- fflush(stdout);
- }
- /* do a re-draw */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* left slider zoom factor */
- static void on_vscale1_changed(GtkAdjustment * adj)
- {
- gdouble val0 = 0.0;
- int val1 = 0;
- if (adj) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- val0 = gtk_adjustment_get_value(adj);
- val1 = (int)val0;
- zfactor = exp((double)(3 * (val1 - 50)) / (double)50);
- if (option_gdebug > 1) {
- printf("%s(): zoomslider=%d zoomfactor=%f\n", __func__, val1, zfactor);
- fflush(stdout);
- }
- /* do a re-draw */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* right slider y offset 0...100% */
- static void on_vscale2_changed(GtkAdjustment * adj, gpointer data)
- {
- gdouble val = 0.0;
- if (data) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- val = gtk_adjustment_get_value(adj);
- vymin = (int)((val * maxy) / 100);
- if (option_gdebug > 1) {
- printf("%s(): yslider=%d vymin=%d (maxy=%d)\n", __func__, (int)val, vymin, maxy);
- fflush(stdout);
- }
- /* do a re-draw */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* right slider y offset 0...100% */
- static void on_vscale2_changed(GtkAdjustment * adj)
- {
- gdouble val = 0.0;
- if (adj) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- val = gtk_adjustment_get_value(adj);
- vymin = (int)((val * maxy) / 100);
- if (option_gdebug > 1) {
- printf("%s(): yslider=%d vymin=%d (maxy=%d)\n", __func__, (int)val, vymin, maxy);
- fflush(stdout);
- }
- /* do a re-draw */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* bottom slider x offset 0...100% */
- static void on_hscale1_changed(GtkAdjustment * adj, gpointer data)
- {
- gdouble val = 0.0;
- if (data) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- val = gtk_adjustment_get_value(adj);
- vxmin = (int)((val * maxx) / 100);
- if (option_gdebug > 1) {
- printf("%s(): xslider=%d vxmin=%d (maxx=%d)\n", __func__, (int)val, vxmin, maxx);
- fflush(stdout);
- }
- /* do a re-draw */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* bottom slider x offset 0...100% */
- static void on_hscale1_changed(GtkAdjustment * adj)
- {
- gdouble val = 0.0;
- if (adj) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- val = gtk_adjustment_get_value(adj);
- vxmin = (int)((val * maxx) / 100);
- if (option_gdebug > 1) {
- printf("%s(): xslider=%d vxmin=%d (maxx=%d)\n", __func__, (int)val, vxmin, maxx);
- fflush(stdout);
- }
- /* do a re-draw */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #endif
- /* draw arrow, option to allow multiple arrow types todo
- * arrow comes from (start_x,start_y) to (end_x,end_y)
- * size is optional, if zero a default size is used
- */
- static void drarrow(cairo_t * crp, int start_x, int start_y, int end_x, int end_y, double size)
- {
- double angle = 0.0;
- double arrow_lenght = 8.0;
- double arrow_degrees = ( /* degrees */ 30 * (M_PI / 180));
- double x1 = 0.0;
- double y1 = 0.0;
- double x2 = 0.0;
- double y2 = 0.0;
- if (yydebug || 0) {
- printf("%s(): arrow at (%d,%d) coming from (%d,%d) size %f\n", __func__, end_x, end_y, start_x, start_y, size);
- }
- /* if size is specified, use it, otherwise use default size */ if (size == 0) {
- arrow_lenght = 8.0;
- } else {
- arrow_lenght = size;
- }
- /* gtk has a gtk_render_arrow() function as alternative to use here */
- angle = atan2(end_y - start_y, end_x - start_x) + M_PI;
- x1 = end_x + arrow_lenght * cos(angle - arrow_degrees);
- y1 = end_y + arrow_lenght * sin(angle - arrow_degrees);
- x2 = end_x + arrow_lenght * cos(angle + arrow_degrees);
- y2 = end_y + arrow_lenght * sin(angle + arrow_degrees);
- /* set start position of arrow part 1 */
- cairo_move_to(crp, end_x, end_y);
- cairo_line_to(crp, x1, y1);
- /* set start position of arrow part 2 */
- cairo_move_to(crp, end_x, end_y);
- cairo_line_to(crp, x2, y2);
- /* make a triangle */
- cairo_line_to(crp, x1, y1);
- return;
- }
- /* */
- static void on_top_level_window_drawingarea1_expose_event_nodes_record_r(cairo_t * crp, struct gml_node
- *node, struct gml_rl
- *info)
- {
- int i = 0;
- int x0 = 0;
- int y0 = 0;
- int r = 0;
- int b = 0;
- int g = 0;
- int xxo = 0;
- int yyo = 0;
- int szx = 0;
- int szy = 0;
- PangoLayout *layout = NULL;
- PangoFontDescription *desc = NULL;
- char buf[128];
- char *s = NULL;
- /* name of font to use, example "Sans" */
- const char *default_fontname = DEFAULT_FONTNAME;
- /* name of slant to use, example "Italic", "Oblique", "Roman" */
- const char *default_fontslant = DEFAULT_FONTSLANT;
- /* name of weight to use, example "Bold", "Book", "Light", "Medium", "Semi-bold", "Ultra-light" */
- const char *default_fontweight = DEFAULT_FONTWEIGHT;
- /* name of condensed to use, example "Semi-Condensed", "Condensed" */
- const char *default_fontcondensed = DEFAULT_FONTCONDENSED;
- /* font size to use, example "10", "18", "20" etc. */
- const char *default_fontsize = DEFAULT_FONTSIZE;
- x0 = node->finx - vxmin;
- y0 = node->finy - vymin;
- if (info->hd == 0) {
- /* not-has-data */
- for (i = 0; i < info->nparts; i++) {
- on_top_level_window_drawingarea1_expose_event_nodes_record_r(crp, node, info->parts[i]);
- }
- } else {
- /* has-data */
- /* black outline color */
- r = 0;
- g = 0;
- b = 0;
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- szx = info->bbx;
- szy = info->bby;
- if (info->dir == 0) {
- if (info->xstep) {
- szx = info->xstep;
- } else {
- szx = info->bbx;
- }
- } else {
- if (info->ystep) {
- szy = info->ystep;
- } else {
- szy = info->bby;
- }
- }
- /* this is the box to put the part of the text in */
- cairo_rectangle(crp, x0 + info->xoff, y0 + info->yoff, szx, szy);
- if (yydebug || 0) {
- printf("%s(): rect at (%d,%d) size (%d,%d) for \"%s\"\n", __func__,
- x0 + info->xoff, y0 + info->yoff, szx, szy, info->ulabel);
- }
- cairo_stroke(crp);
- /* fontcolor of node black default or color */
- r = (node->fontcolor & 0x00ff0000) >> 16;
- g = (node->fontcolor & 0x0000ff00) >> 8;
- b = (node->fontcolor & 0x000000ff);
- /* draw in text fontcolor of node */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- /* start text inside rectangle */
- xxo = 2;
- yyo = 2;
- /* set start position of text */
- cairo_move_to(crp, x0 + info->xoff + xxo, y0 + info->yoff + yyo);
- layout = pango_cairo_create_layout(crp);
- /* set the text to draw which is 0 terminated */
- pango_layout_set_text(layout, info->ulabel, -1);
- /* set font parameters */
- /* create the fontname description */
- memset(buf, 0, (size_t)128);
- default_fontname = DEFAULT_FONTNAME;
- /* check if node has a specified font slant */
- default_fontslant = DEFAULT_FONTSLANT;
- /* check if node has a specified font weight */
- default_fontweight = DEFAULT_FONTWEIGHT;
- /* check if node has a specified font size */
- default_fontsize = DEFAULT_FONTSIZE;
- /* create the font name string */
- snprintf(buf, (128 - 1), "%s %s %s %s %s", default_fontname,
- default_fontslant, default_fontweight, default_fontcondensed, default_fontsize);
- /* copy string buffer */
- s = uniqstr(buf);
- /* */
- desc = pango_font_description_from_string(s);
- /* */
- pango_layout_set_font_description(layout, desc);
- /* */
- pango_font_description_free(desc);
- /* */
- pango_cairo_update_layout(crp, layout);
- /* draw the text */
- pango_cairo_show_layout(crp, layout);
- /* */
- cairo_stroke(crp);
- g_object_unref(G_OBJECT(layout));
- }
- return;
- }
- /* record node drawing */
- static void on_top_level_window_drawingarea1_expose_event_nodes_record(cairo_t * crp, struct gml_node
- *node)
- {
- on_top_level_window_drawingarea1_expose_event_nodes_record_r(crp, node, node->rlabel);
- return;
- }
- /* html 1 item node drawing */ static void on_top_level_window_drawingarea1_expose_event_nodes_html1item(cairo_t * crp, struct gml_node
- *node,
- struct gml_hitem *item,
- int xplus, int yplus)
- {
- PangoLayout *layout = NULL;
- PangoFontDescription *desc = NULL;
- char buf[128];
- int x0 = 0;
- int y0 = 0;
- int r = 0;
- int b = 0;
- int g = 0;
- int fontcolor = 0;
- int bgcolor = 0;
- int bgr = 0;
- int bgb = 0;
- int bgg = 0;
- int xxo = 0;
- int yyo = 0;
- char *s = NULL;
- char *fontstr = NULL;
- PangoAttrList *pattrs = NULL;
- GError *errorpos = NULL;
- int status = 0;
- char *ptext = NULL;
- char *em = NULL;
- char *fnam = NULL;
- char *fslant = NULL;
- char *fweight = NULL;
- char *ful = NULL;
- char *fol = NULL;
- char spans[128];
- char spane[64];
- char *fsubs = NULL;
- char *fsube = NULL;
- char *fsups = NULL;
- char *fsupe = NULL;
- char *fstr = NULL;
- int fsize = 0;
- int flen = 0;
- if (item == NULL) {
- /* shouldnothappen */
- return;
- }
- if (item->text == NULL) {
- /* shouldnothappen */
- return;
- }
- if (strlen(item->text) == 0) {
- /* shouldnothappen */
- return;
- }
- /* start positions */
- x0 = node->finx - vxmin;
- y0 = node->finy - vymin;
- x0 = x0 + xplus;
- y0 = y0 + yplus;
- if (yydebug || 0) {
- printf("%s(): text %s at (%d,%d)\n", __func__, item->text, xplus, yplus);
- }
- layout = pango_cairo_create_layout(crp);
- /* background color */
- if (item->ncolor < 0) {
- /* shouldnothappen */
- bgcolor = 0x00ffff;
- } else {
- bgcolor = item->ncolor;
- }
- /* backgroundcolor of node white default or color */
- bgr = (bgcolor & 0x00ff0000) >> 16;
- bgg = (bgcolor & 0x0000ff00) >> 8;
- bgb = (bgcolor & 0x000000ff);
- if (item->fontcolor < 0) {
- /* shouldnothappen */
- fontcolor = 0; /* black */
- } else {
- fontcolor = item->fontcolor;
- }
- /* fontcolor of node black default or color */
- r = (fontcolor & 0x00ff0000) >> 16;
- g = (fontcolor & 0x0000ff00) >> 8;
- b = (fontcolor & 0x000000ff);
- /* re-use pango font format string */
- if (item->fontstr) {
- fontstr = item->fontstr;
- } else {
- /* create new string */
- if (item->fontname) {
- fnam = item->fontname;
- } else {
- fnam = DEFAULT_FONTNAME;
- }
- if (item->fontslant) {
- fslant = item->fontslant;
- } else {
- fslant = DEFAULT_FONTSLANT;
- }
- if (item->bitflags.i) {
- fslant = "italic";
- }
- if (item->fontweight) {
- fweight = item->fontweight;
- } else {
- fweight = DEFAULT_FONTWEIGHT;
- }
- if (item->bitflags.b) {
- fweight = "bold";
- }
- if (item->bitflags.u || 0) {
- ful = " underline=\"single\"";
- /* also option to set underline color */
- } else {
- ful = "";
- }
- /* also option to set overline color */
- if (item->bitflags.o || 0) {
- if (pango_overline < 0) {
- /* probe pango lib for support at runtime */
- status = pango_parse_markup("<span overline=\"single\">text</span>", -1, 0, &pattrs, &ptext, NULL, &errorpos);
- if (status == 0) {
- printf("%s(): overline <o> in html string is not supported with current pango library\n", __func__);
- pango_overline = 0;
- } else {
- /* supported */
- pango_overline = 1;
- }
- }
- /* it depends on pango version if overline s allowed, if not then no text */
- if (pango_overline) {
- fol = " overline=\"single\"";
- } else {
- fol = "";
- }
- } else {
- fol = "";
- }
- if (item->bitflags.s || 0) {
- fstr = " strikethrough=\"true\"";
- } else {
- fstr = "";
- }
- if (item->fontsize < 0) {
- fsize = DEFAULT_FONTSIZE_INT;
- } else {
- fsize = item->fontsize;
- }
- /* sub and superscript */
- if (item->bitflags.sub || 0) {
- fsubs = "<sub>";
- fsube = "</sub>";
- } else {
- fsubs = "";
- fsube = "";
- }
- if (item->bitflags.sup || 0) {
- fsups = "<sup>";
- fsupe = "</sup>";
- } else {
- fsups = "";
- fsupe = "";
- }
- memset(spans, 0, (size_t)128);
- /* start of format string */
- snprintf(spans, (128 - 1), "<span foreground=\"#%02x%02x%02x\" background=\"#%02x%02x%02x\"%s%s%s>%s%s", r, g, b,
- bgr, bgg, bgb, ful, fstr, fol, fsups, fsubs);
- /* end of format string */
- memset(spane, 0, (size_t)64);
- snprintf(spane, (size_t)(64 - 1), "%s%s</span>", fsube, fsupe);
- flen = strlen(spans) + strlen(spane) + strlen(item->otext) + 1;
- fontstr = dp_calloc(1, flen);
- /* create new full format string */
- strcpy(fontstr, spans);
- strcat(fontstr, item->otext);
- strcat(fontstr, spane);
- /* save for re-use */
- item->fontstr = uniqstr(fontstr);
- fontstr = dp_free(fontstr);
- if (fontstr) {
- }
- fontstr = item->fontstr;
- }
- status = pango_parse_markup(fontstr, -1, 0, &pattrs, &ptext, NULL, &errorpos);
- if (status == 0) {
- if (errorpos) {
- em = errorpos->message;
- } else {
- em = "";
- }
- printf("%s(): pango_parse_markup() of '%s' has error status %d \"%s\"\n", __func__, fontstr, status, em);
- pattrs = NULL;
- }
- /* oke */
- pango_layout_set_text(layout, item->text, -1);
- pango_layout_set_attributes(layout, pattrs);
- if (pango_layout_get_character_count(layout) == 0) {
- /* shouldnothappen */
- g_object_unref(G_OBJECT(layout));
- return;
- }
- /* start text inside rectangle */
- xxo = 1;
- yyo = 1;
- /* set start position of text */
- cairo_move_to(crp, x0 + item->txoff + xxo, y0 + item->tyoff + yyo);
- /* set font parameters */
- /* create the fontname description or re-use */
- if (item->fontdesc) {
- s = item->fontdesc;
- } else {
- memset(buf, 0, (size_t)128);
- /* create the font name string */
- snprintf(buf, (size_t)(128 - 1), "%s %s %s %s %d", fnam, fslant, fweight, DEFAULT_FONTCONDENSED, fsize);
- s = uniqstr(buf);
- item->fontdesc = s;
- }
- /* */
- desc = pango_font_description_from_string(s);
- /* */
- pango_layout_set_font_description(layout, desc);
- /* */
- pango_font_description_free(desc);
- /* */
- pango_cairo_update_layout(crp, layout);
- /* draw the text */
- pango_cairo_show_layout(crp, layout);
- /* */
- cairo_stroke(crp);
- g_object_unref(G_OBJECT(layout));
- return;
- }
- /* html items node drawing */
- static void on_top_level_window_drawingarea1_expose_event_nodes_htmlitems(cairo_t * crp, struct gml_node
- *node, struct gml_hilist *il, int xplus, int yplus)
- {
- struct gml_hitem *pitem = NULL;
- struct gml_hilist *pi = NULL;
- if (il == NULL) {
- /* shouldnothappen */
- return;
- }
- if (yydebug || 0) {
- printf("%s(): node=\"%s\" xyplus=(%d,%d)\n", __func__, node->name, xplus, yplus);
- }
- /* scan the text elements */
- pi = il;
- while (pi) {
- pitem = pi->items;
- if (pitem) {
- if (pi->items->bitflags.br) {
- } else if (pi->items->bitflags.hr) {
- } else if (pi->items->bitflags.vr) {
- } else if (pi->items->bitflags.img) {
- } else if (pi->items->bitflags.table) {
- } else {
- on_top_level_window_drawingarea1_expose_event_nodes_html1item(crp, node, pitem, xplus, yplus);
- }
- }
- pi = pi->next;
- }
- return;
- }
- /* zzz */
- /* html tables node drawing */
- static void on_top_level_window_drawingarea1_expose_event_nodes_1htmltable(cairo_t * crp, struct gml_node
- *node, struct gml_htlist *tlptr)
- {
- struct gml_tritemlist *trptr = NULL; /* list of <tr> items in this table */
- struct gml_tditem *tdiptr = NULL;
- struct gml_hilist *ilptr = NULL; /* list of text items */
- struct gml_htlist *tlptrsub = NULL;
- int yo = 0;
- int xo = 0;
- int nyo = 0;
- int nxo = 0;
- int itemrectanglecolor = 0; /* color of outline rectangle of item, 0 is black, #rrggbb */
- int r = 0;
- int g = 0;
- int b = 0;
- int tabxoff = 0;
- int tabyoff = 0;
- int tabxsize = 0;
- int tabysize = 0;
- int tabncols = 0;
- int tabnrows = 0;
- int trnumtd = 0;
- int trysize = 0;
- int tdxsize = 0;
- int ytd = 0;
- if (tlptr == NULL) {
- printf("%s(): nil tlptr\n", __func__);
- /* shouldnothappen */
- return;
- }
- if (tlptr->titem == NULL) {
- printf("%s(): nil titem\n", __func__);
- /* shouldnothappen */
- return;
- }
- /* scan the items in this <table> */
- nxo = node->finx - vxmin;
- nyo = node->finy - vymin;
- /* (x,y) offset of <table> */
- tabxoff = tlptr->titem->xoff;
- tabyoff = tlptr->titem->yoff;
- if (tabxoff) { /* todo */
- }
- if (tabyoff) { /* todo */
- }
- if (yydebug || 0) {
- printf("%s(): <table> offset is (%d,%d)\n", __func__, tabxoff, tabyoff);
- }
- /* start draw at table offset */
- /* xo = tabxoff; not used here */
- yo = tabyoff;
- /* (x,y) size of <table> */
- tabxsize = tlptr->titem->txsize;
- tabysize = tlptr->titem->tysize;
- if (tabxsize) { /* todo */
- }
- if (tabysize) { /* todo */
- }
- /* (x,y) size of table in cols/rows */
- tabncols = tlptr->titem->ncols;
- tabnrows = tlptr->titem->nrows;
- if (tabncols) { /* todo */
- }
- if (tabnrows) { /* todo */
- }
- /* */
- if (tlptr->titem->tr) {
- trptr = tlptr->titem->tr;
- while (trptr) {
- /* scan the <tr> items */
- if (trptr->tritem) {
- /* number of <td> items at this <tr> */
- trnumtd = trptr->tritem->numtd;
- if (trnumtd) { /* todo */
- }
- /* y size of this <tr> */
- trysize = trptr->tritem->ysize;
- /* */
- tdiptr = trptr->tritem->tdi;
- if (tdiptr) {
- /* scan the <td> items */
- xo = tabxoff;
- while (tdiptr) {
- /* x size of this <td> */
- tdxsize = tdiptr->xsize;
- if (tdxsize) { /* todo not used here */
- }
- /* there are dummy <td> with no item data in it, but color, size is set */
- ilptr = tdiptr->il;
- if (ilptr) {
- ytd = 0;
- while (ilptr) {
- /* colored rectangle around item, option here. */
- r = ((itemrectanglecolor & 0x00ff0000) >> 16);
- g = ((itemrectanglecolor & 0x0000ff00) >> 8);
- b = (itemrectanglecolor & 0x000000ff);
- /* */
- /* */
- if (yydebug || 0) {
- printf
- ("%s(): <td> at (%d,%d) size (%d,%d) \"%s\"\n",
- __func__, xo, yo + ytd, ilptr->items->txsize, ilptr->items->tysize, ilptr->items->text);
- }
- /* */
- if (ilptr->items->bitflags.br) {
- } else if (ilptr->items->bitflags.hr) {
- } else if (ilptr->items->bitflags.vr) {
- } else if (ilptr->items->bitflags.img) {
- } else if (ilptr->items->bitflags.table) {
- if (yydebug || 0) {
- printf
- ("%s(): table bit set todo xstep=%d xo=%d yo+ytd=%d\n",
- __func__, tdiptr->xstep, xo, yo + ytd);
- }
- ilptr->items->table->xoff = xo;
- ilptr->items->table->yoff = yo + ytd;
- } else {
- if (yydebug || 0) {
- printf("%s(): items at (%d,%d)\n", __func__, xo, yo + ytd);
- }
- /* html items node drawing */
- on_top_level_window_drawingarea1_expose_event_nodes_html1item(crp, node, ilptr->items,
- /* int xplus */
- xo,
- /* int yplus */
- yo + ytd);
- }
- ytd = ytd + ilptr->items->tysize;
- ilptr = ilptr->next;
- }
- }
- /* there can be dummy <td> */
- /* test */
- if (0) {
- /* test only */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- cairo_rectangle(crp, xo + nxo, yo + nyo, tdxsize, trysize);
- cairo_stroke(crp); /* ccx */
- } else {
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- cairo_rectangle(crp, xo + nxo, yo + nyo, tdiptr->xstep, tdiptr->ystep);
- cairo_stroke(crp); /* ccx */
- }
- /* */
- /* to next <td> */
- xo = xo + 2;
- xo = xo + tdiptr->xstep;
- tdiptr = tdiptr->next;
- }
- /* end of <td> */
- yo = yo + trysize;
- }
- }
- trptr = trptr->next;
- }
- }
- /* scan the sub <table> items in this <table> */
- if (tlptr->titem->tl) {
- tlptrsub = tlptr->titem->tl;
- while (tlptrsub) {
- on_top_level_window_drawingarea1_expose_event_nodes_1htmltable(crp, node, tlptrsub);
- tlptrsub = tlptrsub->next;
- }
- }
- return;
- }
- /* html tables node drawing */
- static void on_top_level_window_drawingarea1_expose_event_nodes_htmltables(cairo_t * crp, struct gml_node
- *node)
- {
- struct gml_htlist *tlptr = NULL;
- if (node->hlabel->tl == NULL) {
- /* shouldnothappen */
- return;
- }
- /* */ tlptr = node->hlabel->tl;
- while (tlptr) {
- on_top_level_window_drawingarea1_expose_event_nodes_1htmltable(crp, node, tlptr);
- tlptr = tlptr->next;
- }
- return;
- }
- /* html node drawing */
- static void on_top_level_window_drawingarea1_expose_event_nodes_html(cairo_t * crp, struct gml_node
- *node)
- {
- if (node->hlabel->mode == 0) {
- /* items */
- on_top_level_window_drawingarea1_expose_event_nodes_htmlitems(crp, node, node->hlabel->il, 0, 0);
- } else {
- /* tables */
- on_top_level_window_drawingarea1_expose_event_nodes_htmltables(crp, node);
- }
- return;
- }
- /* draw all nodes z
- zzz*/
- static void on_top_level_window_drawingarea1_expose_event_nodes(cairo_t * crp)
- {
- int xo = 0;
- int yo = 0;
- double dfs = 0.0;
- int fs = 0;
- int r = 0;
- int g = 0;
- int b = 0;
- PangoLayout *layout = NULL;
- PangoFontDescription *desc = NULL;
- char buf[128];
- char *s = NULL;
- /* name of font to use, example "Sans" */
- const char *default_fontname = DEFAULT_FONTNAME;
- /* name of slant to use, example "Italic", "Oblique", "Roman" */
- const char *default_fontslant = DEFAULT_FONTSLANT;
- /* name of weight to use, example "Bold", "Book", "Light", "Medium", "Semi-bold", "Ultra-light" */
- const char *default_fontweight = DEFAULT_FONTWEIGHT;
- /* name of condensed to use, example "Semi-Condensed", "Condensed" */
- const char *default_fontcondensed = DEFAULT_FONTCONDENSED;
- /* font size to use, example "10", "18", "20" etc. */
- const char *default_fontsize = DEFAULT_FONTSIZE;
- int x0 = 0;
- int y0 = 0;
- struct gml_nlist *nl = NULL;
- nl = maingraph->nodelist;
- while (nl) {
- /* only draw real nodes here or draw edge-label */
- if (nl->node->dummy == 0) {
- x0 = nl->node->finx - vxmin;
- y0 = nl->node->finy - vymin;
- /* first draw circle is node has a selfedge */
- if (nl->node->elabel == 0) {
- if (nl->node->nselfedges) {
- /* black or colored selfedge */
- r = (nl->node->secolor & 0x00ff0000) >> 16;
- g = ((nl->node->secolor & 0x0000ff00) >> 8);
- b = (nl->node->secolor & 0x000000ff);
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- /* draw the self-edge, whole circle */
- cairo_arc(crp, x0 + nl->node->bbx - 3, y0 + nl->node->bby - 3, 6 /* radius */ ,
- 0 /* 45 * (180 * M_PI) */ , 2 * M_PI);
- /* opt. arrow, which is too big here todo. this looks not good */
- if (0) {
- drarrow(crp, x0 - 10, y0 + nl->node->bby - 6, x0, y0 + nl->node->bby - 6, 3);
- }
- cairo_stroke(crp);
- }
- }
- /* fillcolor of node white default or color */
- r = ((nl->node->ncolor & 0x00ff0000) >> 16);
- g = ((nl->node->ncolor & 0x0000ff00) >> 8);
- b = (nl->node->ncolor & 0x000000ff);
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- cairo_rectangle(crp, x0, y0, nl->node->bbx, nl->node->bby);
- cairo_fill(crp);
- cairo_stroke(crp);
- /* outline color black for node, edgelabel node has no outline */
- if (nl->node->elabel == 0) {
- /* bordercolor of node black default or color */
- r = (nl->node->nbcolor & 0x00ff0000) >> 16;
- g = (nl->node->nbcolor & 0x0000ff00) >> 8;
- b = (nl->node->nbcolor & 0x000000ff);
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- cairo_rectangle(crp, x0, y0, nl->node->bbx, nl->node->bby);
- cairo_stroke(crp);
- } else {
- /* this is a edge label, no outline */
- }
- /* draw no text labels if labels==0 */
- if (option_labels == 0) {
- nl = nl->next;
- continue;
- }
- /*
- * now draw text of label as ususal or record style label
- */
- /* this below is not oke, todo to fix */
- /* calculate the scaled font size */
- dfs = (zfactor * atoi(default_fontsize));
- /* somewhat rounded version */
- fs = (int)dfs;
- /* too small to draw readable text then skip the following text drawing area */
- if (fs < 4) {
- nl = nl->next;
- continue;
- }
- if (yydebug || 0) {
- printf("%s(): drawrh=%d\n", __func__, nl->node->drawrh);
- }
- if (nl->node->drawrh) {
- /* draw regular text in node, or record label */
- if (nl->node->hlabel) {
- /* draw html label */
- on_top_level_window_drawingarea1_expose_event_nodes_html(crp, nl->node);
- } else if (nl->node->rlabel) {
- /* draw record label */
- on_top_level_window_drawingarea1_expose_event_nodes_record(crp, nl->node);
- } else {
- /* draw regular text */
- /* fontcolor of node black default or color */
- r = (nl->node->fontcolor & 0x00ff0000) >> 16;
- g = (nl->node->fontcolor & 0x0000ff00) >> 8;
- b = (nl->node->fontcolor & 0x000000ff);
- /* draw in text color of node */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- xo = 2;
- yo = 2;
- /* set start position of text */
- cairo_move_to(crp, nl->node->finx - vxmin + xo, nl->node->finy - vymin + yo);
- layout = pango_cairo_create_layout(crp);
- if (nl->node->nlabel == NULL) {
- printf("%s(): nil nlabel\n", __func__);
- /* shouldnothappen */
- nl->node->nlabel = nl->node->name;
- }
- /* set the text to draw which is 0 terminated */
- pango_layout_set_text(layout, nl->node->nlabel, -1);
- /* set font parameters */
- /* create the fontname description */
- memset(buf, 0, (size_t)128);
- default_fontname = DEFAULT_FONTNAME;
- /* check if node has a specified font slant */
- default_fontslant = DEFAULT_FONTSLANT;
- /* check if node has a specified font weight */
- default_fontweight = DEFAULT_FONTWEIGHT;
- /* check if node has a specified font size */
- default_fontsize = DEFAULT_FONTSIZE;
- /* create the font name string */
- snprintf(buf, (128 - 1), "%s %s %s %s %s", default_fontname,
- default_fontslant, default_fontweight, default_fontcondensed, default_fontsize);
- /* copy string buffer */
- s = uniqstr(buf);
- /* */
- desc = pango_font_description_from_string(s);
- /* */
- pango_layout_set_font_description(layout, desc);
- /* */
- pango_font_description_free(desc);
- /* */
- pango_cairo_update_layout(crp, layout);
- /* draw the text */
- pango_cairo_show_layout(crp, layout);
- /* */
- cairo_stroke(crp);
- g_object_unref(G_OBJECT(layout));
- }
- } else {
- /* draw regular text */
- /* fontcolor of node black default or color */
- r = (nl->node->fontcolor & 0x00ff0000) >> 16;
- g = (nl->node->fontcolor & 0x0000ff00) >> 8;
- b = (nl->node->fontcolor & 0x000000ff);
- /* draw in text color of node */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- xo = 2;
- yo = 2;
- /* set start position of text */
- cairo_move_to(crp, nl->node->finx - vxmin + xo, nl->node->finy - vymin + yo);
- layout = pango_cairo_create_layout(crp);
- /* set the text to draw which is 0 terminated */
- pango_layout_set_text(layout, nl->node->name, -1);
- /* set font parameters */
- /* create the fontname description */
- memset(buf, 0, (size_t)128);
- default_fontname = DEFAULT_FONTNAME;
- /* check if node has a specified font slant */
- default_fontslant = DEFAULT_FONTSLANT;
- /* check if node has a specified font weight */
- default_fontweight = DEFAULT_FONTWEIGHT;
- /* check if node has a specified font size */
- default_fontsize = DEFAULT_FONTSIZE;
- /* create the font name string */
- snprintf(buf, (128 - 1), "%s %s %s %s %s", default_fontname,
- default_fontslant, default_fontweight, default_fontcondensed, default_fontsize);
- /* copy string buffer */
- s = uniqstr(buf);
- /* */
- desc = pango_font_description_from_string(s);
- /* */
- pango_layout_set_font_description(layout, desc);
- /* */
- pango_font_description_free(desc);
- /* */
- pango_cairo_update_layout(crp, layout);
- /* draw the text */
- pango_cairo_show_layout(crp, layout);
- /* */
- cairo_stroke(crp);
- g_object_unref(G_OBJECT(layout));
- }
- }
- nl = nl->next;
- }
- return;
- }
- /* real-to-dummy find edge conn. point */
- static int r2d_finx(struct gml_edge *edge)
- {
- struct gml_node *sn = NULL;
- struct gml_node *tn = NULL;
- int ret = 0;
- int i = 0;
- sn = edge->from_node; /* from-node */
- tn = edge->to_node; /* to-node */
- if (tn) {
- }
- if (edge->vedge) {
- ret = (sn->finx + (sn->bbx / 2));
- return (ret);
- }
- if (sn->dx_oedges == 0) {
- ret = (sn->finx + (sn->bbx / 2));
- return (ret);
- }
- for (i = 0; i < sn->outdegree; i++) {
- if (sn->oedges[i] == edge) {
- break;
- }
- }
- ret = (sn->finx + 5 + (i * sn->dx_oedges));
- return (ret);
- }
- /* connection edge at real to-node */
- static int d2r_tnx1(struct gml_edge *edge)
- {
- struct gml_node *sn = NULL;
- struct gml_node *tn = NULL;
- int ret = 0;
- int i = 0;
- sn = edge->from_node; /* from-node */
- tn = edge->to_node; /* to-node */
- if (sn) {
- }
- if (edge->vedge) {
- ret = (tn->finx + (tn->bbx / 2));
- return (ret);
- }
- if (tn->dx_iedges == 0) {
- ret = (tn->finx + (tn->bbx / 2));
- return (ret);
- }
- for (i = 0; i < tn->indegree; i++) {
- if (tn->iedges[i] == edge) {
- break;
- }
- }
- ret = (tn->finx + 5 + (i * tn->dx_iedges));
- return (ret);
- }
- /* nr. of pixels hor. edge goes downwards */
- #define HEDGE_DY 10
- /* draw dummy nodes in the drawing */
- static void on_drawdummy(cairo_t * crp, int mode, int dx, int dy)
- {
- double radius = 3.0;
- double x = (double)dx;
- double y = (double)dy;
- if (mode == 0) {
- /* draw red filled rectangle size 5x5 pixels */
- cairo_set_source_rgb(crp, 255 / 255.0, 0 / 255.0, 0 / 255.0);
- cairo_rectangle(crp, x - 3, y - 3, 5, 5);
- cairo_fill(crp);
- } else if (mode == 1) {
- /* draw orange circle not filled */
- cairo_set_source_rgb(crp, 255 / 255.0, 140 / 255.0, 0 / 255.0);
- /* 360 degree circle */
- cairo_arc(crp, x, y, radius, 0.0, (double)(2 * M_PI));
- } else if (mode == 2) {
- /* draw fluor orange circle filled */
- cairo_set_source_rgb(crp, 255 / 255.0, 191 / 255.0, 0 / 255.0);
- /* 360 degree circle */
- cairo_arc(crp, x, y, radius, 0.0, (double)(2 * M_PI));
- cairo_fill(crp);
- } else if (mode == 3) {
- /* draw pale circle filled */
- cairo_set_source_rgb(crp, 152 / 255.0, 251 / 255.0, 152 / 255.0);
- /* 360 degree circle */
- cairo_arc(crp, x, y, radius, 0.0, (double)(2 * M_PI));
- cairo_fill(crp);
- } else {
- /* draw pink circle filled */
- cairo_set_source_rgb(crp, 255 / 255.0, 105 / 255.0, 180 / 255.0);
- /* 360 degree circle */
- cairo_arc(crp, x, y, radius, 0.0, (double)(2 * M_PI));
- cairo_fill(crp);
- }
- cairo_stroke(crp);
- return;
- }
- /* draw all edges
- * the barycenter gives node a relative (x,y) position in (x,y) and (relx,rely)
- * the pos.c trnslates this in absolute (x,y) coordinates in (finx,finy)
- * the virtual window top upper left corner is at (vxmin,vymin)
- * the virtual window is moved using the sliders
- * the zoom factor of the drawing is in (double) zfactor and used by cairo
- * the node (x,y) size needed for the shape with the text is in (bbx,bby)
- * the nodes are in vertical levels put in the middle of the level
- * the top of the level of the node is in ly0
- * the start of the top level of the node is in lx0
- * the bottom of the level of the node is in ly1
- * the start of the bottom level of the node is in lx2
- * the dummy node has flag dummy set to 1
- * the edge label node has flag elabel set to 1
- * the horizontal edge has flag hedge set and must be routed differently
- * the node has in nselfedges number of self edges at the node
- * the drawing of self edges is extra part and creates other drawing problems
- * the routing of edges is in graphviz really very complex
- * this should also use a more complex solution for spline drawing
- * the chaikin algorithm can be used to draw better spline edges
- * this shuld be pre-calculated in the edge data also hor. edge routing to be added
- */
- static void on_top_level_window_drawingarea1_expose_event_edges(cairo_t * crp)
- {
- int r = 0;
- int g = 0;
- int b = 0;
- int fnx1 = 0;
- int fny1 = 0;
- int tnx1 = 0;
- int tny1 = 0;
- struct gml_elist *el = NULL;
- struct gml_edge *edge = NULL;
- struct gml_node *sn = NULL;
- struct gml_node *tn = NULL;
- int ecolor = 0;
- int dx15 = 0;
- const double dashed[] = {
- 14.0, 2.0 /* 6.0 */
- };
- int lendashed = sizeof(dashed) / sizeof(dashed[0]);
- const double dotted[] = {
- 1.0 /* 2.0, 6.0 */
- };
- int lendotted = sizeof(dotted) / sizeof(dotted[0]);
- int px1 = 0;
- int py1 = 0;
- int px2 = 0;
- int py2 = 0;
- int test = 0; /* set to 1 for test */
- el = maingraph->edgelist;
- while (el) {
- edge = el->edge;
- sn = edge->from_node; /* from-node */
- tn = edge->to_node; /* to-node */
- ecolor = edge->ecolor; /* edge line color */
- /* thickness of edge line */
- cairo_set_line_width(crp, DEFAULT_EDGE_THICKNESS);
- /* check edge line style */
- if (edge->style == 1 /* ESTYLE_DASHED */ ) {
- /* dashed edge line */
- cairo_set_dash(crp, dashed, lendashed, 1);
- } else if (edge->style == 2 /* ESTYLE_DOTTED */ ) {
- /* dotted edge line */
- cairo_set_dash(crp, dotted, lendotted, 0);
- } else {
- /* solid edge line */
- cairo_set_dash(crp, dotted, 0, 0);
- }
- /* black or colored line */
- r = (ecolor & 0x00ff0000) >> 16;
- g = (ecolor & 0x0000ff00) >> 8;
- b = (ecolor & 0x000000ff);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- if (edge->hedge) {
- /* horizontal edge has original endpoints */
- /* center of from/to nodes */
- fnx1 = (sn->finx + sn->bbx / 2) - vxmin;
- tnx1 = (tn->finx + tn->bbx / 2) - vxmin;
- if (tnx1 > fnx1) {
- /* edge from left to right */
- /* check if nodes are next to each other */
- /* this should also check if to-node is a dummy or real node todo */
- if ((sn->relx + 1) == tn->relx) {
- /* printf ("direct-lr\n"); */
- fnx1 = (sn->finx + sn->bbx) - vxmin;
- fny1 = (sn->finy + sn->bby / 2) - vymin;
- cairo_move_to(crp, fnx1, fny1);
- cairo_line_to(crp, (tn->finx) - vxmin, (tn->finy + tn->bby / 2) - vymin);
- /* add arrow */
- if (edge->reversed == 0) {
- drarrow(crp, fnx1, fny1, (tn->finx) - vxmin, (tn->finy + tn->bby / 2) - vymin, 0);
- } else {
- drarrow(crp, (tn->finx) - vxmin, (tn->finy + tn->bby / 2) - vymin, fnx1, fny1, 0);
- }
- } else {
- /* distance length of hor. line / 5 */
- dx15 = (tnx1 - fnx1) / 5;
- /* optional draw hor. edges in a different color */
- if (0) {
- cairo_set_source_rgb(crp, 0 / 255.0, 0 / 255.0, 0xff / 255.0);
- }
- /* start line at center */
- fnx1 = (sn->finx + sn->bbx / 2) - vxmin;
- fny1 = (sn->finy + sn->bby) - vymin;
- cairo_move_to(crp, fnx1, fny1);
- if ((sn->finy + sn->bby) >= (tn->finy + tn->bby)) {
- /* from node y is lower then target, put hor. line 10px lower */
- cairo_line_to(crp, (fnx1 + dx15), ((sn->finy + sn->bby) + HEDGE_DY) - vymin);
- cairo_line_to(crp, (fnx1 + dx15) + (3 * dx15), ((sn->finy + sn->bby) + HEDGE_DY) - vymin);
- cairo_line_to(crp, (tn->finx + tn->bbx / 2) - vxmin, (tn->finy + tn->bby) - vymin);
- /* add arrow */
- if (edge->reversed == 0) {
- drarrow(crp, (fnx1 + dx15) + (3 * dx15),
- ((sn->finy + sn->bby) + HEDGE_DY) -
- vymin, (tn->finx + tn->bbx / 2) - vxmin, (tn->finy + tn->bby) - vymin, 0);
- } else {
- if (0) { /*old */
- drarrow(crp, (fnx1 + dx15), ((sn->finy + sn->bby) + HEDGE_DY) - vymin, fnx1, fny1, 0);
- }
- drarrow(crp,
- (tn->finx + tn->bbx / 2) - vxmin,
- (tn->finy + tn->bby) - vymin,
- (fnx1 + dx15) + (3 * dx15), ((sn->finy + sn->bby) + HEDGE_DY) - vymin, 0);
- }
- } else {
- /* from-node y is higher */
- cairo_line_to(crp, (fnx1 + dx15), (tn->finy + tn->bby) + HEDGE_DY - vymin);
- cairo_line_to(crp, (fnx1 + dx15) + (3 * dx15), ((tn->finy + tn->bby) + HEDGE_DY) - vymin);
- cairo_line_to(crp, (tn->finx + tn->bbx / 2) - vxmin, (tn->finy + tn->bby) - vymin);
- /* add arrow */
- if (edge->reversed == 0) {
- drarrow(crp, (fnx1 + dx15) + (3 * dx15),
- ((tn->finy + tn->bby) + HEDGE_DY) -
- vymin, (tn->finx + tn->bbx / 2) - vxmin, (tn->finy + tn->bby) - vymin, 0);
- } else {
- drarrow(crp, (fnx1 + dx15), (tn->finy + tn->bby) + HEDGE_DY - vymin, fnx1, fny1, 0);
- }
- }
- }
- } else {
- /* edge from right to left fnx1>tnx1 */
- if ((sn->relx) == (tn->relx + 1)) {
- /* printf ("direct-rl\n"); */
- cairo_move_to(crp, (sn->finx) - vxmin, (sn->finy + sn->bby / 2) - vymin);
- cairo_line_to(crp, tn->finx + tn->bbx - vxmin, tn->finy + tn->bby / 2 - vymin);
- /* add arrow */
- if (edge->reversed == 0) {
- drarrow(crp,
- (sn->finx) - vxmin,
- (sn->finy + sn->bby / 2) - vymin, tn->finx + tn->bbx - vxmin, tn->finy + tn->bby / 2 - vymin, 0);
- } else {
- drarrow(crp, tn->finx + tn->bbx - vxmin,
- tn->finy + tn->bby / 2 - vymin, (sn->finx) - vxmin, (sn->finy + sn->bby / 2) - vymin, 0);
- }
- } else {
- /* distance length of hor. line / 5 */
- dx15 = (fnx1 - tnx1) / 5;
- /* optional draw hor. edges in a different color */
- if (0) {
- cairo_set_source_rgb(crp, 0 / 255.0, 0 / 255.0, 0xff / 255.0);
- }
- /* start line at center */
- fnx1 = (sn->finx + sn->bbx / 2) - vxmin;
- fny1 = (sn->finy + sn->bby) - vymin;
- cairo_move_to(crp, fnx1, fny1);
- if ((sn->finy + sn->bby) >= (tn->finy + tn->bby)) {
- /* from node y is lower then target, put hor. line 10px lower */
- cairo_line_to(crp, (fnx1 - dx15), ((sn->finy + sn->bby) + HEDGE_DY) - vymin);
- cairo_line_to(crp, (fnx1 - dx15) - (3 * dx15), ((sn->finy + sn->bby) + HEDGE_DY) - vymin);
- cairo_line_to(crp, (tn->finx + tn->bbx / 2) - vxmin, (tn->finy + tn->bby) - vymin);
- /* add arrow */
- if (edge->reversed == 0) {
- /* could be improved here todo */
- drarrow(crp, (fnx1 - dx15) - (3 * dx15),
- ((sn->finy + sn->bby) +
- HEDGE_DY) - vymin, (tn->finx + tn->bbx / 2) - vxmin, (tn->finy + tn->bby) - vymin, 0);
- } else {
- drarrow(crp, (fnx1 - dx15), ((sn->finy + sn->bby) + HEDGE_DY) - vymin, fnx1, fny1, 0);
- }
- } else {
- /* from-node y is higher */
- cairo_line_to(crp, (fnx1 - dx15), (tn->finy + tn->bby) + HEDGE_DY - vymin);
- cairo_line_to(crp, (fnx1 - dx15) - (3 * dx15), ((tn->finy + tn->bby) + HEDGE_DY) - vymin);
- cairo_line_to(crp, (tn->finx + tn->bbx / 2) - vxmin, (tn->finy + tn->bby) - vymin);
- /* add arrow */
- if (edge->reversed == 0) {
- /* this could be improved, todo */
- drarrow(crp, (fnx1 - dx15) - (3 * dx15),
- ((sn->finy + sn->bby) +
- HEDGE_DY) - vymin, (tn->finx + tn->bbx / 2) - vxmin, (tn->finy + tn->bby) - vymin, 0);
- } else {
- drarrow(crp, (fnx1 - dx15), (tn->finy + tn->bby) + HEDGE_DY - vymin, fnx1, fny1, 0);
- }
- }
- }
- }
- } else {
- /* here if not a horizontal edge */
- if (option_splines) {
- /* drawing spline lines */
- if (0) {
- printf("%s(): edge `%s'->`%s' reversed=%d\n", __func__, sn->nlabel, tn->nlabel, edge->reversed);
- }
- if (sn->dummy == 0 && tn->dummy == 0) {
- /* from real node to real node.
- * real nodes are interleaved with dummy nodes
- * this only does happen from real node to edge-label node
- */
- /* from point at bottom of node */
- fnx1 = (sn->finx + sn->bbx / 2) - vxmin;
- fny1 = (sn->finy + sn->bby) - vymin;
- cairo_move_to(crp, (double)fnx1, (double)fny1);
- /* to point at top of node */
- tnx1 = (tn->finx + tn->bbx / 2) - vxmin;
- tny1 = (tn->finy) - vymin;
- cairo_line_to(crp, (double)tnx1, (double)tny1);
- /* optional draw dummy node */
- if (option_drawdummy) {
- /* light baby pink */
- cairo_set_source_rgb(crp, 245 / 255.0, 195 / 255.0, 194 / 255.0);
- cairo_move_to(crp, (double)(fnx1 + 2), (double)fny1);
- cairo_line_to(crp, (double)(tnx1 + 2), (double)tny1);
- cairo_stroke(crp);
- on_drawdummy(crp, 0 /* red rectangle */ , (double)fnx1, (double)fny1);
- on_drawdummy(crp, 0 /* red rectangle */ , (double)tnx1, (double)tny1);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- }
- /* add arrow */
- if (edge->reversed == 0) {
- drarrow(crp, fnx1, fny1, tnx1, tny1, 0);
- } else {
- drarrow(crp, tnx1, tny1, fnx1, fny1, 0);
- }
- } else if (sn->dummy == 1 && tn->dummy == 0) {
- /* from dummy node to real node */
- fnx1 = sn->finx - vxmin;
- fny1 = sn->finy - vymin;
- tnx1 = d2r_tnx1(edge) - vxmin;
- tny1 = tn->finy - vymin;
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- if (0) { /* straight lines */
- cairo_move_to(crp, fnx1, fny1);
- cairo_line_to(crp, fnx1, fny1 + (sn->bby / 2));
- cairo_line_to(crp, tnx1, (tn->ly0 - vymin));
- cairo_line_to(crp, tnx1, tny1);
- } else {
- /* temp fixed */
- cairo_move_to(crp, (double)fnx1, (double)fny1);
- px1 = fnx1;
- py1 = fny1 + (sn->bby / 2);
- px2 = tnx1;
- py2 = (tn->ly0 - vymin);
- cairo_curve_to(crp, (double)fnx1, (double)fny1, px1, py1, px2, py2);
- cairo_line_to(crp, (double)tnx1, (double)tny1);
- cairo_stroke(crp);
- }
- /* optional draw dummy node */
- if (option_drawdummy) {
- /* light red */
- cairo_set_source_rgb(crp, 255 / 255.0, 204 / 255.0, 203 / 255.0);
- /* +2 to put the colored line next to the original line */
- cairo_move_to(crp, (double)(fnx1 + 2), (double)fny1);
- cairo_line_to(crp, px1, py1);
- cairo_line_to(crp, px2, py2);
- cairo_line_to(crp, (double)(tnx1 + 2), (double)tny1);
- cairo_stroke(crp);
- on_drawdummy(crp, 0 /* red rectangle */ , (double)fnx1, (double)fny1);
- on_drawdummy(crp, 0 /* red rectangle */ , (double)tnx1, (double)tny1);
- on_drawdummy(crp, 1, px1, py1);
- on_drawdummy(crp, 1, px2, py2);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- }
- /* add arrow */
- if (edge->reversed == 0) {
- drarrow(crp, fnx1, fny1, tnx1, tny1, 0);
- } else {
- /* no arrow */
- }
- cairo_stroke(crp);
- } else if (sn->dummy == 0 && tn->dummy == 1) {
- /* from real node to dummy node */
- fnx1 = r2d_finx(edge) - vxmin;
- fny1 = (sn->finy + sn->bby) - vymin;
- tnx1 = tn->finx - vxmin;
- tny1 = tn->finy - vymin;
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- /* optional draw dummy node */
- if (option_drawdummy) {
- cairo_set_source_rgb(crp, 255 / 255.0, 0 / 255.0, 0 / 255.0);
- cairo_rectangle(crp, tnx1 - 1, tny1 - 1, 3, 3);
- cairo_fill(crp);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- }
- if (0) { /* straight */
- cairo_move_to(crp, fnx1, fny1);
- cairo_line_to(crp, fnx1, (sn->ly1 - vymin));
- cairo_line_to(crp, tnx1, tny1 - (tn->bby / 2));
- cairo_line_to(crp, tnx1, tny1);
- } else {
- /* fixed */
- cairo_move_to(crp, (double)fnx1, (double)fny1);
- /* todo p1 p2 points */
- px1 = fnx1;
- py1 = (sn->ly1 - vymin);
- px2 = tnx1;
- py2 = tny1 - (tn->bby / 2);
- cairo_curve_to(crp, px1, py1, px2, py2, (double)tnx1, (double)tny1);
- cairo_stroke(crp);
- }
- /* optional draw dummy node */
- if (option_drawdummy) {
- /* peach puff light orange */
- cairo_set_source_rgb(crp, 255 / 255.0, 218 / 255.0, 185 / 255.0);
- cairo_move_to(crp, (double)(fnx1 + 2), (double)fny1);
- cairo_line_to(crp, px1, py1);
- cairo_line_to(crp, px2, py2);
- cairo_line_to(crp, (double)(tnx1 + 2), (double)tny1);
- cairo_stroke(crp);
- on_drawdummy(crp, 0 /* red rectangle */ , (double)fnx1, (double)fny1);
- on_drawdummy(crp, 0 /* red rectangle */ , (double)tnx1, (double)tny1);
- on_drawdummy(crp, 2, px1, py1);
- on_drawdummy(crp, 2, px2, py2);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- }
- /* add arrow */
- if (edge->reversed == 0) {
- /* no arrow */
- } else {
- drarrow(crp, tnx1, tny1, fnx1, fny1, 0);
- }
- cairo_stroke(crp);
- } else {
- /* from dummy node to dummy node */
- fnx1 = sn->finx - vxmin;
- fny1 = sn->finy - vymin;
- tnx1 = tn->finx - vxmin;
- tny1 = tn->finy - vymin;
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- if (test || 0) { /* straight */
- cairo_move_to(crp, fnx1, fny1);
- cairo_line_to(crp, fnx1, fny1 + (sn->bby / 2));
- cairo_line_to(crp, tnx1, (tn->ly0 - vymin));
- cairo_line_to(crp, tnx1, tny1 - (tn->bby / 2));
- cairo_line_to(crp, tnx1, tny1);
- } else {
- cairo_move_to(crp, fnx1, fny1);
- cairo_line_to(crp, fnx1, fny1 + (sn->bby / 2));
- cairo_stroke(crp);
- /* also possible px1 = (((fnx1 * 2) + tnx1) / 3); px2 = ((fnx1 + (tnx1 * 2)) / 3); */
- cairo_move_to(crp, fnx1, fny1 + (sn->bby / 2));
- cairo_curve_to(crp, tnx1, (tn->ly0 - vymin), tnx1, tny1 - (tn->bby / 2), tnx1, tny1);
- px1 = tnx1;
- py1 = (tn->ly0 - vymin);
- px2 = tnx1;
- py2 = tny1 - (tn->bby / 2);
- cairo_stroke(crp);
- }
- /* optional draw dummy node */
- if (option_drawdummy) {
- /* light green */
- cairo_set_source_rgb(crp, 173 / 255.0, 255 / 255.0, 47 / 255.0);
- cairo_move_to(crp, (double)(fnx1 + 2), (double)fny1);
- cairo_line_to(crp, (double)(fnx1 + 2), (double)(fny1 + (sn->bby / 2)));
- cairo_line_to(crp, px1, py1);
- cairo_line_to(crp, px2, py2);
- cairo_line_to(crp, (double)(tnx1 + 2), (double)tny1);
- cairo_stroke(crp);
- on_drawdummy(crp, 0 /* red rectangle */ , (double)fnx1, (double)fny1);
- on_drawdummy(crp, 0 /* red rectangle */ , (double)tnx1, (double)tny1);
- on_drawdummy(crp, 3, px1, py1);
- on_drawdummy(crp, 3, px2, py2);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- }
- /* no real nodes, no arrows, optional draw arrows at dummy nodes, see tuxsee */
- }
- } else {
- /* drawing not-spline lines */
- if (sn->dummy == 0 && tn->dummy == 0) {
- /* from real node to real node.
- * real nodes are interleaved with dummy nodes
- * this does happen from real node to edge-label node
- */
- /* from real node to real node */
- fnx1 = sn->finx + sn->bbx / 2 - vxmin;
- fny1 = sn->finy + sn->bby - vymin;
- cairo_move_to(crp, fnx1, fny1);
- tnx1 = tn->finx + tn->bbx / 2 - vxmin;
- tny1 = tn->finy - vymin;
- cairo_line_to(crp, tnx1, tny1);
- /* add arrow */
- if (edge->reversed == 0) {
- drarrow(crp, fnx1, fny1, tnx1, tny1, 0);
- } else {
- drarrow(crp, tnx1, tny1, fnx1, fny1, 0);
- }
- } else if (sn->dummy == 1 && tn->dummy == 0) {
- /* from dummy node to real node */
- fnx1 = sn->finx - vxmin;
- fny1 = sn->finy - vymin;
- tnx1 = d2r_tnx1(edge) - vxmin;
- tny1 = tn->finy - vymin;
- /* optional draw dummy node */
- if (option_drawdummy) {
- cairo_set_source_rgb(crp, 255 / 255.0, 0 / 255.0, 0 / 255.0);
- cairo_rectangle(crp, fnx1 - 1, fny1 - 1, 3, 3);
- cairo_fill(crp);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- }
- cairo_move_to(crp, fnx1, fny1);
- cairo_line_to(crp, fnx1, fny1 + (sn->bby / 2));
- cairo_line_to(crp, tnx1, (tn->ly0 - vymin));
- cairo_line_to(crp, tnx1, tny1);
- /* add arrow */
- if (edge->reversed == 0) {
- drarrow(crp, fnx1, fny1, tnx1, tny1, 0);
- } else {
- /* no arrow */
- }
- } else if (sn->dummy == 0 && tn->dummy == 1) {
- /* from real node to dummy node */
- fnx1 = r2d_finx(edge) - vxmin;
- fny1 = (sn->finy + sn->bby) - vymin;
- tnx1 = tn->finx - vxmin;
- tny1 = tn->finy - vymin;
- /* optional draw dummy node */
- if (option_drawdummy) {
- cairo_set_source_rgb(crp, 255 / 255.0, 0 / 255.0, 0 / 255.0);
- cairo_rectangle(crp, tnx1 - 1, tny1 - 1, 3, 3);
- cairo_fill(crp);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- }
- cairo_move_to(crp, fnx1, fny1);
- cairo_line_to(crp, fnx1, (sn->ly1 - vymin));
- cairo_line_to(crp, tnx1, tny1 - (tn->bby / 2));
- cairo_line_to(crp, tnx1, tny1);
- /* add arrow */
- if (edge->reversed == 0) {
- /* no arrow */
- } else {
- drarrow(crp, tnx1, tny1, fnx1, fny1, 0);
- }
- } else {
- /* from dummy node to dummy node */
- fnx1 = sn->finx - vxmin;
- fny1 = sn->finy - vymin;
- tnx1 = tn->finx - vxmin;
- tny1 = tn->finy - vymin;
- /* optional draw dummy node */
- if (option_drawdummy) {
- cairo_set_source_rgb(crp, 255 / 255.0, 0 / 255.0, 0 / 255.0);
- cairo_rectangle(crp, fnx1 - 2, fny1 - 2, 5, 5);
- cairo_fill(crp);
- cairo_rectangle(crp, tnx1 - 2, tny1 - 2, 5, 5);
- cairo_fill(crp);
- /* draw in line color of edge */
- cairo_set_source_rgb(crp, r / 255.0, g / 255.0, b / 255.0);
- }
- cairo_move_to(crp, fnx1, fny1);
- cairo_line_to(crp, fnx1, fny1 + (sn->bby / 2));
- cairo_line_to(crp, tnx1, (tn->ly0 - vymin));
- cairo_line_to(crp, tnx1, tny1 - (tn->bby / 2));
- cairo_line_to(crp, tnx1, tny1);
- /* no arrow draw because there are no real nodes */
- }
- /* put the lines on screen */
- cairo_stroke(crp);
- }
- }
- cairo_stroke(crp);
- el = el->next;
- }
- return;
- }
- #if (GTK_HAVE_API_VERSION_2 == 1)
- /* redraw drawing area */
- static gboolean on_top_level_window_drawingarea1_expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer user_data)
- {
- cairo_t *crdraw = NULL;
- gint w = 0; /* xsize of drawing area */
- gint h = 0; /* ysize of drawing area */
- int fit = 0;
- if (widget) {
- }
- if (event == NULL) {
- return (FALSE);
- }
- if (user_data) {
- }
- /* only at first expose */
- if (drawing_area_xsize == 0 && drawing_area_ysize == 0) {
- fit = 1;
- } else {
- fit = 0;
- }
- if (fit) {
- }
- /* get cairo drawing context */
- crdraw = gdk_cairo_create(event->window);
- /* how large drawing area is */
- (void)gdk_drawable_get_size(event->window, &w, &h);
- if (option_gdebug > 1 || 0) {
- printf("%s(): drawing area size is (%d,%d)\n", __func__, w, h);
- fflush(stdout);
- }
- /* save a copy of current size */
- drawing_area_xsize = w;
- drawing_area_ysize = h;
- /* check if there is node data to draw */
- if (validdata == 0) {
- /* white fill drawing area */
- cairo_set_source_rgb(crdraw, altr / 255.0, altg / 255.0, altb / 255.0);
- cairo_rectangle(crdraw, 0, 0, w, h);
- cairo_fill(crdraw);
- cairo_stroke(crdraw);
- cairo_destroy(crdraw);
- /* no data */
- return (FALSE);
- }
- cairo_set_source_rgb(crdraw, bgcr / 255.0, bgcg / 255.0, bgcb / 255.0);
- /* select whole screen to fill with background color */
- cairo_rectangle(crdraw, 0, 0, w, h);
- cairo_fill(crdraw);
- cairo_stroke(crdraw);
- /* use zoom slider drawing scale */
- cairo_scale(crdraw, zfactor, zfactor);
- on_top_level_window_drawingarea1_expose_event_nodes(crdraw);
- on_top_level_window_drawingarea1_expose_event_edges(crdraw);
- /* ready drawing */
- cairo_destroy(crdraw);
- return (FALSE);
- }
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* draw on screen */
- static void draw_function_for_gtk4(GtkDrawingArea * area, cairo_t * crdraw, int width, int height, gpointer user_data)
- {
- if (area) {
- }
- if (user_data) {
- }
- if (option_gdebug > 1 || 0) {
- printf("%s(): drawing area size is (%d,%d)\n", __func__, width, height);
- fflush(stdout);
- }
- /* save a copy of current size */
- drawing_area_xsize = width;
- drawing_area_ysize = height;
- /* check if there is node data to draw */
- if (validdata == 0) {
- /* fill drawing area with a light-grey color */
- cairo_set_source_rgb(crdraw, altr / 255.0, altg / 255.0, altb / 255.0);
- cairo_rectangle(crdraw, 0, 0, drawing_area_xsize, drawing_area_ysize);
- cairo_fill(crdraw);
- cairo_stroke(crdraw);
- /* no cairo_destroy(crdraw); needed */
- /* no data */
- return;
- }
- /* set current background color parsed from graph data */
- cairo_set_source_rgb(crdraw, bgcr / 255.0, bgcg / 255.0, bgcb / 255.0);
- /* select whole screen to fill with background color */
- cairo_rectangle(crdraw, 0, 0, drawing_area_xsize, drawing_area_ysize);
- cairo_fill(crdraw);
- cairo_stroke(crdraw);
- /* use zoom slider drawing scale */
- cairo_scale(crdraw, zfactor, zfactor);
- on_top_level_window_drawingarea1_expose_event_nodes(crdraw);
- on_top_level_window_drawingarea1_expose_event_edges(crdraw);
- /* no cairo_destroy(crdraw); needed */
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- /* redraw drawing area */
- static gboolean on_top_level_window_drawingarea1_draw_event(GtkWidget * widget, cairo_t * crdraw, gpointer user_data)
- {
- gint w = 0; /* xsize of drawing area */
- gint h = 0; /* ysize of drawing area */
- cairo_t *crp = NULL;
- if (widget) {
- }
- if (user_data) {
- }
- /* this is a workaround for issue in cairo-lib 1.14.0 with gtk3,
- * cairo.c cairo_destroy() line 305 assert(), (with gtk2 no problem) */
- crp = cairo_reference(crdraw);
- /* how large drawing area is */
- w = gtk_widget_get_allocated_width(drawingarea1);
- h = gtk_widget_get_allocated_height(drawingarea1);
- if (option_gdebug > 1) {
- printf("%s(): drawing area size is (%d,%d)\n", __func__, w, h);
- fflush(stdout);
- }
- /* save a copy of current size */
- drawing_area_xsize = w;
- drawing_area_ysize = h;
- /* check if there is node data to draw */
- if (validdata == 0) {
- /* white fill drawing area */
- cairo_set_source_rgb(crdraw, altr / 255.0, altg / 255.0, altb / 255.0);
- cairo_rectangle(crdraw, 0, 0, w, h);
- cairo_fill(crdraw);
- cairo_stroke(crdraw);
- cairo_destroy(crdraw);
- /* no data */
- return (FALSE);
- }
- cairo_set_source_rgb(crdraw, bgcr / 255.0, bgcg / 255.0, bgcb / 255.0);
- /* select whole screen to fill with background color */
- cairo_rectangle(crdraw, 0, 0, w, h);
- cairo_fill(crdraw);
- cairo_stroke(crdraw);
- /* use zoom slider drawing scale */
- cairo_scale(crdraw, zfactor, zfactor);
- on_top_level_window_drawingarea1_expose_event_nodes(crdraw);
- on_top_level_window_drawingarea1_expose_event_edges(crdraw);
- cairo_destroy(crp);
- return (FALSE);
- }
- #endif
- /* update status text */
- static void update_status_text(char *text)
- {
- /* update status text line */
- memset(charentry1buffer, 0, (size_t)64);
- /* */
- if (text) {
- snprintf(charentry1buffer, (size_t)(64 - 1), "%s", text);
- if (option_gdebug > 1 || 0) {
- printf("%s(): %s\n", __func__, text);
- fflush(stdout);
- }
- } else {
- if (maingraph) {
- /* some info about the graph, based on parsed data */
- snprintf(charentry1buffer, (64 - 1),
- "%d nodes, %d edges, %d crossings, size (%d,%d)",
- maingraph->tnnodes, maingraph->tnedges, maingraph->sugi_fcrossings, maxx, maxy);
- } else {
- snprintf(charentry1buffer, 64 - 1, "no message");
- }
- }
- /* when running in console mode there is no entry1buffer */
- if (entry1buffer) {
- gtk_text_buffer_set_text(entry1buffer, charentry1buffer, -1);
- /* it is visible in the gui */
- /* only a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- }
- return;
- }
- /* */
- void update_status_text_cross(char *text)
- {
- /* does not work as expected */
- return;
- update_status_text(text);
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- while (gtk_main_iteration()) {
- /* this should update the status text */ ;
- }
- #endif
- return;
- }
- /* checkbox 1 is 'splines' */
- static void check1_toggle(GtkWidget * widget, gpointer arg)
- {
- gboolean status = FALSE;
- if (widget) {
- }
- if (arg) {
- }
- /* toggle the splines option */
- #if (GTK_HAVE_API_VERSION_4 == 1)
- status = gtk_check_button_get_active(GTK_CHECK_BUTTON(widget));
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- #endif
- if (status == TRUE) {
- option_splines = 1;
- } else {
- option_splines = 0;
- }
- /* only a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* checkbox 2 is 'dummy's' draw dummy nodes */
- static void dummy1_toggle(GtkWidget * widget, gpointer window)
- {
- gboolean status = FALSE;
- if (widget) {
- }
- if (window) {
- }
- /* toggle the splines option */
- #if (GTK_HAVE_API_VERSION_4 == 1)
- status = gtk_check_button_get_active(GTK_CHECK_BUTTON(widget));
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- #endif
- if (status == TRUE) {
- option_drawdummy = 1;
- } else {
- option_drawdummy = 0;
- }
- /* only a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* checkbox 5 is switch edge labels */
- static void elabel1_toggle(GtkWidget * widget, gpointer window)
- {
- gboolean status = FALSE;
- if (widget) {
- }
- if (window) {
- }
- /* when no labels do not draw edge labels */
- if (option_labels == 0) {
- return;
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- status = gtk_check_button_get_active(GTK_CHECK_BUTTON(widget));
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- #endif
- /* toggle the splines option */
- if (status == TRUE) {
- option_edgelabels = 1;
- } else {
- option_edgelabels = 0;
- }
- /* nop if no data */
- if (validdata == 0) {
- return;
- }
- /* if no edgelabels, skip */
- if (maingraph->tnedgelabels == 0) {
- return;
- }
- /* do re-layout */
- do_relayout_all(maingraph);
- /* now a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* checkbox 6 is switch labels */
- static void label1_toggle(GtkWidget * widget, gpointer window)
- {
- gboolean status = FALSE;
- if (widget) {
- }
- if (window) {
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- status = gtk_check_button_get_active(GTK_CHECK_BUTTON(widget));
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- #endif
- /* toggle the splines option */
- if (status == TRUE) {
- option_labels = 1;
- } else {
- option_labels = 0;
- }
- /* nop if no data */
- if (validdata == 0) {
- return;
- }
- /* force edgelabels off */
- option_edgelabels = 0;
- #if (GTK_HAVE_API_VERSION_4 == 1)
- gtk_check_button_set_active(GTK_CHECK_BUTTON(elabel1), FALSE);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elabel1), FALSE);
- #endif
- /* do re-layout */
- do_relayout_all(maingraph);
- /* now a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* checkbox 7 is node names instead of labels */
- static void nnames1_toggle(GtkWidget * widget, gpointer window)
- {
- gboolean status = FALSE;
- if (widget) {
- }
- if (window) {
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- status = gtk_check_button_get_active(GTK_CHECK_BUTTON(widget));
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- #endif
- /* toggle the splines option */
- if (status == TRUE) {
- option_nnames = 1;
- } else {
- option_nnames = 0;
- }
- /* nop if no data */
- if (validdata == 0) {
- return;
- }
- /* do re-layout */
- do_relayout_all(maingraph);
- /* now a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* checkbox 8 is mirror in y direction */
- static void mirrory1_toggle(GtkWidget * widget, gpointer window)
- {
- gboolean status = FALSE;
- if (widget) {
- }
- if (window) {
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- status = gtk_check_button_get_active(GTK_CHECK_BUTTON(widget));
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- #endif
- /* toggle the splines option */
- if (status == TRUE) {
- option_mirrory = 1;
- } else {
- option_mirrory = 0;
- }
- /* nop if no data */
- if (validdata == 0) {
- return;
- }
- /* force postype */
- postype = 1;
- /* set the value for the new pos type */
- gtk_spin_button_set_value((GtkSpinButton *) posbutton, postype);
- /* do re-layout */
- do_relayout_all(maingraph);
- /* now a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* checkbox 7 is switch popup labels */
- static void popup1_toggle(GtkWidget * widget, gpointer window)
- {
- gboolean status = FALSE;
- if (widget) {
- }
- if (window) {
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- status = gtk_check_button_get_active(GTK_CHECK_BUTTON(widget));
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- #endif
- /* toggle the splines option */
- if (status == TRUE) {
- option_popup = 1;
- } else {
- option_popup = 0;
- }
- /* nop if no data */
- if (validdata == 0) {
- return;
- }
- /* no redraw needed */
- return;
- }
- /* changed type */
- static void pos_changed(GtkWidget * widget, gpointer spinbutton)
- {
- #if (GTK_HAVE_API_VERSION_4 == 1)
- GtkSpinButton *spin = NULL;
- #endif
- gfloat val = 0.0;
- if (widget) {
- }
- if (spinbutton) {
- }
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- /* at mirrory option force to keep postype 1 because type 2 does not work anymore. */
- if (option_mirrory) {
- /* message why pos value does not changes */
- printf("%s(): because mirror option is active pos mode is fixed to 1 or turn off mirror option\n", __func__);
- fflush(stdout);
- postype = 1;
- #if (GTK_HAVE_API_VERSION_4 == 1)
- spin = GTK_SPIN_BUTTON(widget);
- gtk_spin_button_set_value(spin, postype);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* set the value for the new pos type */
- gtk_spin_button_set_value((GtkSpinButton *) posbutton, postype);
- #endif
- return;
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- spin = GTK_SPIN_BUTTON(widget);
- val = gtk_spin_button_get_value(spin);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* get the value for the new pos type */
- val = gtk_spin_button_get_value((GtkSpinButton *) spinbutton);
- #endif
- /* set new pos type, 1,2,3,4 */
- postype = (int)val;
- if (1) {
- /* temp complete layout to make sure draw points are correct but can be replaced with below */
- /* do re-layout */
- do_relayout_all(maingraph);
- }
- /* todo to implement below otherwise draw control points are not correct */
- if (0) {
- /* re-calc positions */
- improve_positions(maingraph);
- /* final (x,y) positioning of nodes/edges */
- finalxy(maingraph);
- /* calculate edge connections */
- edgeconnections(maingraph);
- /* update sub parts of drawing */
- positionz(maingraph);
- /* update status text */
- update_status_text(NULL);
- }
- /* only a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* stretch in x direction */
- static void xspin_changed(GtkWidget * widget, gpointer spinbutton)
- {
- #if (GTK_HAVE_API_VERSION_4 == 1)
- GtkSpinButton *spin = NULL;
- #endif
- gfloat val = 0.0;
- if (widget) {
- }
- if (spinbutton) {
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- spin = GTK_SPIN_BUTTON(widget);
- val = gtk_spin_button_get_value(spin);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* get the value for the new drawing spreading factor */
- val = gtk_spin_button_get_value((GtkSpinButton *) spinbutton);
- #endif
- /* set new spreading factor */
- xspacing = (int)val;
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- /* re-calc positions */
- improve_positions(maingraph);
- /* final (x,y) positioning of nodes/edges */
- finalxy(maingraph);
- /* calculate edge connections */
- edgeconnections(maingraph);
- /* update sub parts of drawing */
- positionz(maingraph);
- /* update status text */
- update_status_text(NULL);
- /* only a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- static void yspin_changed(GtkWidget * widget, gpointer spinbutton)
- {
- #if (GTK_HAVE_API_VERSION_4 == 1)
- GtkSpinButton *spin = NULL;
- #endif
- gfloat val = 0.0;
- if (widget) {
- }
- if (spinbutton) {
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- spin = GTK_SPIN_BUTTON(widget);
- val = gtk_spin_button_get_value(spin);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* get the value for the new drawing spreading factor */
- val = gtk_spin_button_get_value((GtkSpinButton *) spinbutton);
- #endif
- /* set new spreading factor */
- yspacing = (int)val;
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- /* re-calc positions */
- improve_positions(maingraph);
- /* final (x,y) positioning of nodes/edges */
- finalxy(maingraph);
- /* calculate edge connections */
- edgeconnections(maingraph);
- /* update sub parts of drawing */
- positionz(maingraph);
- /* update status text */
- update_status_text(NULL);
- /* only a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* changed type */
- static void bary_changed(GtkWidget * widget, gpointer spinbutton)
- {
- #if (GTK_HAVE_API_VERSION_4 == 1)
- GtkSpinButton *spin = NULL;
- #endif
- gfloat val = 0.0;
- if (widget) {
- }
- if (spinbutton) {
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- spin = GTK_SPIN_BUTTON(widget);
- val = gtk_spin_button_get_value(spin);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* get the value for the new bary type */
- val = gtk_spin_button_get_value((GtkSpinButton *) spinbutton);
- #endif
- /* set new bary type, 1,2,3 or 4 */
- barytype = (int)val;
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- /* re-layout */
- do_relayout_all(maingraph);
- /* now a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- /* changed type */
- static void rank_changed(GtkWidget * widget, gpointer spinbutton)
- {
- #if (GTK_HAVE_API_VERSION_4 == 1)
- GtkSpinButton *spin = NULL;
- #endif
- gfloat val = 0.0;
- if (widget) {
- }
- if (spinbutton) {
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- spin = GTK_SPIN_BUTTON(widget);
- val = gtk_spin_button_get_value(spin);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* get the value for the new bary type */
- val = gtk_spin_button_get_value((GtkSpinButton *) spinbutton);
- #endif
- /* set new rank type, 1,2,3 or 4 */
- ranktype = (int)val;
- /* check if there is node data to draw */
- if (validdata == 0) {
- return;
- }
- /* re-layout */
- do_relayout_all(maingraph);
- /* now a re-draw needed */
- gtk_widget_queue_draw(drawingarea1);
- return;
- }
- #if (GTK_HAVE_API_VERSION_4 == 1)
- /* fit drawing in window */
- static void dofit(void)
- {
- double xzscale = 1.0;
- double yzscale = 1.0;
- double newzscale = 1.0;
- double dval = 1.0;
- int val = 0;
- /* if no maxx, maxy is set */
- if (maxx == 0) {
- maxx = 1;
- }
- if (maxy == 0) {
- maxy = 1;
- }
- xzscale = (double)(1000 * drawing_area_xsize / maxx);
- yzscale = (double)(1000 * drawing_area_ysize / maxy);
- xzscale = xzscale / 1000.0;
- yzscale = yzscale / 1000.0;
- if ((xzscale - yzscale) > 0) {
- newzscale = yzscale;
- } else {
- newzscale = xzscale;
- }
- if (option_gdebug > 1) {
- printf
- ("%s(): dval=%f fit zoom to %f from xscale=%f and yscale=%f drawingarea=(%d,%d) maxy=(%d,%d)\n",
- __func__, dval, newzscale, yzscale, xzscale, drawing_area_xsize, drawing_area_ysize, maxx, maxy);
- }
- /* old dval = log ((newzscale * (double) 50.0) / 3.0) - 50.0; */
- dval = log(newzscale) / 3.0;
- dval = (dval * 50.0);
- dval = dval + 50.0;
- val = (int)dval;
- if (val < 0) {
- val = 0;
- }
- if (val > 100) {
- val = 100;
- }
- zfactor = exp((double)(3 * (val - 50)) / (double)50);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale1), val);
- if (option_gdebug > 1) {
- printf("%s(): new slider value is %d (dval=%f) zfactor=%f\n", "dofit", val, dval, zfactor);
- }
- /* reset v xy min */
- vxmin = 0;
- vymin = 0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), 0);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), 0);
- return;
- }
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* fit drawing in window */
- static void dofit(void)
- {
- double xzscale = 1.0;
- double yzscale = 1.0;
- double newzscale = 1.0;
- double dval = 1.0;
- int val = 0;
- /* if no maxx, maxy is set */
- if (maxx == 0) {
- maxx = 1;
- }
- if (maxy == 0) {
- maxy = 1;
- }
- xzscale = (double)(1000 * drawing_area_xsize / maxx);
- yzscale = (double)(1000 * drawing_area_ysize / maxy);
- xzscale = xzscale / 1000.0;
- yzscale = yzscale / 1000.0;
- if ((xzscale - yzscale) > 0) {
- newzscale = yzscale;
- } else {
- newzscale = xzscale;
- }
- if (option_gdebug > 1) {
- printf
- ("%s(): dval=%f fit zoom to %f from xscale=%f and yscale=%f drawingarea=(%d,%d) maxy=(%d,%d)\n",
- __func__, dval, newzscale, yzscale, xzscale, drawing_area_xsize, drawing_area_ysize, maxx, maxy);
- }
- /* old dval = log ((newzscale * (double) 50.0) / 3.0) - 50.0; */
- dval = log(newzscale) / 3.0;
- dval = (dval * 50.0);
- dval = dval + 50.0;
- val = (int)dval;
- if (val < 0) {
- val = 0;
- }
- if (val > 100) {
- val = 100;
- }
- zfactor = exp((double)(3 * (val - 50)) / (double)50);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale1), val);
- if (option_gdebug > 1) {
- printf("%s(): new slider value is %d (dval=%f) zfactor=%f\n", "dofit", val, dval, zfactor);
- }
- /* reset v xy min */
- vxmin = 0;
- vymin = 0;
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjvscale2), 0);
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adjhscale1), 0);
- return;
- }
- #endif
- /* size of fields */
- static struct gml_p *static_maingtk_textsizes1sz(struct gml_rl *info)
- {
- struct gml_p *data = NULL;
- struct gml_p *dsub = NULL;
- int i = 0;
- data = dp_calloc(1, sizeof(struct gml_p));
- if (info == NULL) { /* shouldnothappen */
- return (data);
- }
- if (info->hd) {
- data->x = info->txsize;
- data->y = info->tysize;
- } else {
- for (i = 0; i < info->nparts; i++) {
- dsub = static_maingtk_textsizes1sz(info->parts[i]);
- if (info->dir == 0) {
- data->x = data->x + dsub->x;
- if (dsub->y > data->y) {
- data->y = dsub->y;
- }
- } else {
- if (dsub->x > data->x) {
- data->x = dsub->x;
- }
- data->y = data->y + dsub->y;
- }
- dsub = dp_free(dsub);
- if (dsub) {
- }
- }
- }
- info->bbx = data->x;
- info->bby = data->y;
- if (yydebug || 0) {
- printf
- ("%s(): hd=%d dir=%d bb(x,y) size is (%d,%d) t(x,x) is (%d,%d) for `%s'\n",
- __func__, info->hd, info->dir, info->bbx, info->bby, info->txsize, info->tysize, info->ulabel);
- }
- return (data);
- }
- static void static_maingtk_textsizes1eq(struct gml_rl *info)
- {
- int i = 0;
- int eqx = 0;
- int eqy = 0;
- int xs = 0;
- int ys = 0;
- int mbbx = 0;
- int mbby = 0;
- char *sdir = NULL;
- if (info == NULL) {
- return;
- }
- if (info->nparts == 0) {
- if (yydebug || 0) {
- printf("%s(): skip \"%s\"\n", __func__, info->ulabel);
- }
- return;
- }
- if (info->hd == 0) {
- /* */
- for (i = 0; i < info->nparts; i++) {
- if (info->parts[i]) {
- if (info->dir == 0) {
- info->parts[i]->bby = info->bby;
- } else {
- info->parts[i]->bbx = info->bbx;
- }
- }
- }
- for (i = 0; i < info->nparts; i++) {
- if (info->parts[i]) {
- if (i == 0) {
- mbbx = info->parts[i]->bbx;
- mbby = info->parts[i]->bby;
- }
- if (info->parts[i]->bbx > mbbx) {
- mbbx = info->parts[i]->bbx;
- }
- if (info->parts[i]->bby > mbby) {
- mbby = info->parts[i]->bby;
- }
- }
- }
- if (yydebug || 0) {
- printf("%s(): info->bbxy(%d,%d) versus mbbxy(%d,%d)\n", __func__, info->bbx, info->bby, mbbx, mbby);
- }
- xs = info->bbx / info->nparts;
- ys = info->bby / info->nparts;
- eqx = 1;
- eqy = 1;
- /* check if parts are same size */
- for (i = 0; i < info->nparts; i++) {
- if (info->parts[i]) {
- if (info->parts[i]->bbx > xs) {
- eqx = 0;
- }
- if (info->parts[i]->bby > ys) {
- eqy = 0;
- }
- }
- }
- /* set step factor if equal spread */
- for (i = 0; i < info->nparts; i++) {
- if (info->parts[i]) {
- if (eqx) {
- info->parts[i]->xstep = xs;
- } else {
- info->parts[i]->xstep = 0;
- }
- if (eqy) {
- info->parts[i]->ystep = ys;
- } else {
- info->parts[i]->ystep = 0;
- }
- if (yydebug || 0) {
- printf("%s(): \"%s\" eqx=%d eqy=%d\n", __func__, info->parts[i]->ulabel, eqx, eqy);
- }
- }
- }
- /* print summary */
- if (yydebug || 0) {
- if (info->dir == 0) {
- sdir = "x-dir";
- } else {
- sdir = "y-dir";
- }
- printf
- ("%s(): size (%d,%d) %s %d parts eqx=%d eqy=%d xstep %d ystep %d\n",
- __func__, info->bbx, info->bby, sdir, info->nparts, eqx, eqy, xs, ys);
- for (i = 0; i < info->nparts; i++) {
- if (info->parts[i]) {
- printf("\t[%d] size (%d,%d) \"%s\" xstep=%d ystep=%d\n", i,
- info->parts[i]->bbx, info->parts[i]->bby,
- info->parts[i]->ulabel, info->parts[i]->xstep, info->parts[i]->ystep);
- }
- }
- }
- for (i = 0; i < info->nparts; i++) {
- if (info->parts[i]) {
- static_maingtk_textsizes1eq(info->parts[i]);
- }
- }
- }
- return;
- }
- /* text size 1 record label */
- static void static_maingtk_textsizes1rl(struct gml_rl *info)
- {
- int i = 0;
- size_t len = 0;
- char *tmpb = NULL;
- char *p = NULL;
- char *q = NULL;
- cairo_surface_t *surface = NULL;
- cairo_t *crdraw = NULL;
- PangoLayout *layout = NULL;
- PangoFontDescription *desc = NULL;
- int w = 0;
- int h = 0;
- char buf[128];
- char *s = NULL;
- /* name of font to use, example "Sans" */
- const char *default_fontname = DEFAULT_FONTNAME;
- /* name of slant to use, example "Italic", "Oblique", "Roman" */
- const char *default_fontslant = DEFAULT_FONTSLANT;
- /* name of weight to use, example "Bold", "Book", "Light", "Medium", "Semi-bold", "Ultra-light" */
- const char *default_fontweight = DEFAULT_FONTWEIGHT;
- /* name of condensed to use, example "Semi-Condensed", "Condensed" */
- const char *default_fontcondensed = DEFAULT_FONTCONDENSED;
- /* font size to use, example "10", "18", "20" etc. */
- const char *default_fontsize = DEFAULT_FONTSIZE;
- if (info == NULL) {
- return;
- }
- /* check if has data */
- if (info->hd) {
- if (info->txsize == 0 && info->tysize == 0) {
- if (info->label == NULL) {
- /* shouldnothappen */
- info->label = uniqstr(" ");
- }
- len = strlen(info->label);
- if (len) {
- tmpb = (char *)dp_calloc(1, (len + 1));
- p = info->label;
- q = tmpb;
- /* un-escape the string */
- while (*p) {
- if (*p == '\\') {
- p++;
- if (*p == 0) {
- *q = '\\';
- q++;
- break;
- }
- if (*p == 'n' || *p == 'l' || *p == 'r') {
- *q = '\n';
- } else {
- *q = *p;
- }
- p++;
- q++;
- } else {
- *q = *p;
- p++;
- q++;
- }
- }
- len = strlen(tmpb);
- if (len) {
- if (tmpb[len - 1] == '\n') {
- tmpb[len - 1] = 0;
- }
- } else {
- info->ulabel = uniqstr(" ");
- }
- info->ulabel = uniqstr(tmpb);
- tmpb = dp_free(tmpb);
- if (tmpb) {
- }
- /* calculate the text area */
- if (surface == NULL) {
- surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10);
- }
- /* */
- if (crdraw == NULL) {
- crdraw = cairo_create(surface);
- }
- /* */
- layout = pango_cairo_create_layout(crdraw);
- /* set the text to draw which is 0 terminated */
- pango_layout_set_text(layout, info->ulabel, -1);
- /* create the fontname description */
- memset(buf, 0, (size_t)128);
- /* name of font to use */
- default_fontname = uniqstr((char *)DEFAULT_FONTNAME);
- /* check if node has a specified font slant */
- default_fontslant = uniqstr((char *)DEFAULT_FONTSLANT);
- /* check if node has a specified font weight */
- default_fontweight = uniqstr((char *)DEFAULT_FONTWEIGHT);
- /* check if node has a specified font size */
- default_fontsize = uniqstr((char *)DEFAULT_FONTSIZE);
- /* create the font name string */
- snprintf(buf, (128 - 1), "%s %s %s %s %s",
- default_fontname, default_fontslant, default_fontweight, default_fontcondensed, default_fontsize);
- /* copy string buffer */
- s = uniqstr(buf);
- /* */
- desc = pango_font_description_from_string(s);
- /* */
- pango_layout_set_font_description(layout, desc);
- /* */
- pango_font_description_free(desc);
- /* */
- pango_cairo_update_layout(crdraw, layout);
- /* */
- w = 0;
- h = 0;
- /* */
- pango_layout_get_size(layout, &w, &h);
- /* */
- g_object_unref(G_OBJECT(layout));
- /* */
- cairo_destroy(crdraw);
- crdraw = NULL;
- /* */
- cairo_surface_destroy(surface);
- surface = NULL;
- /* */
- info->txsize = (w / PANGO_SCALE);
- info->tysize = (h / PANGO_SCALE);
- /* add small margin around text */
- info->txsize = info->txsize + 4;
- info->tysize = info->tysize + 4;
- /* */
- if (yydebug || 0) {
- printf("%s(): (%d,%d) size for `%s'\n", __func__, info->txsize, info->tysize, info->ulabel);
- }
- } else {
- /* at "" string */
- info->txsize = 4;
- info->tysize = 4;
- info->ulabel = uniqstr(" ");
- }
- }
- }
- for (i = 0; i < info->nparts; i++) {
- /* this can be 0 */
- if (info->parts) {
- static_maingtk_textsizes1rl(info->parts[i]);
- }
- }
- return;
- }
- static void static_maingtk_textsizes2rl(struct gml_rl *info, int count, int xoff, int yoff, int bbx, int bby)
- {
- int i = 0;
- char *sdir = NULL;
- int xo = 0;
- int yo = 0;
- int ibbx = 0;
- int ibby = 0;
- int abbx = 0;
- int abby = 0;
- if (info == NULL) {
- return;
- }
- /* check if has data */
- if (info->hd == 0) {
- if (yydebug || 0) {
- printf
- ("%s(%d): xyoff(%d,%d) bbxy(%d,%d) nparts=%d info->bbxy(%d,%d)\n",
- __func__, count, xoff, yoff, bbx, bby, info->nparts, info->bbx, info->bby);
- }
- if (yydebug || 0) {
- if (info->dir == 0) {
- sdir = "x-dir";
- } else {
- sdir = "y-dir";
- }
- printf("%s(): rl=%p %s hd=0 bbxy(%d,%d) nparts=%d\n", __func__, (void *)info, sdir, info->bbx, info->bby, info->nparts);
- for (i = 0; i < info->nparts; i++) {
- if (info->parts[i]) {
- if (info->dir == 0) {
- sdir = "x-dir";
- } else {
- sdir = "y-dir";
- }
- printf("\tparts[%d]=%p %s hd=%d \"%s\"\n", i,
- (void *)info->parts[i], sdir, info->parts[i]->hd, info->parts[i]->ulabel);
- }
- }
- }
- xo = 0;
- yo = 0;
- abbx = 0;
- abby = 0;
- for (i = 0; i < info->nparts; i++) {
- if (info->parts[i]) {
- if (info->parts[i]->hd == 0) {
- ibbx = info->parts[i]->bbx;
- ibby = info->parts[i]->bby;
- abbx = ibbx;
- abby = ibby;
- static_maingtk_textsizes2rl(info->parts[i], i, xoff + xo, yoff + yo, ibbx, ibby);
- /*
- */
- if ((i + 1) < info->nparts) {
- if (info->parts[i + 1]) {
- if (info->parts[i + 1]->hd == 0) {
- if (info->parts[i]->dir == 0) {
- yo = yo + abby;
- } else {
- xo = xo + abbx;
- }
- }
- }
- }
- /*
- *
- */
- } else {
- if (info->parts[i]->dir == 0) {
- info->parts[i]->xoff = xoff + xo + abbx;
- info->parts[i]->yoff = yoff + yo;
- info->parts[i]->bby = bby;
- if (info->parts[i]->xstep) {
- xo = xo + info->parts[i]->xstep + abbx;
- } else {
- xo = xo + info->parts[i]->bbx + abbx;
- }
- } else {
- info->parts[i]->xoff = xoff + xo;
- info->parts[i]->yoff = yoff + yo + abby;
- info->parts[i]->bbx = bbx;
- if (info->parts[i]->ystep) {
- yo = yo + info->parts[i]->ystep + abby;
- } else {
- yo = yo + info->parts[i]->bby + abby;
- }
- }
- abbx = 0;
- abby = 0;
- }
- } /* if (info->parts[i]) */
- } /* for() */
- } else {
- /* info has data */
- if (yydebug || 0) {
- if (info->dir == 0) {
- sdir = "x-dir";
- } else {
- sdir = "y-dir";
- }
- printf
- ("%s(): rl=%p %s hd=1 bbxy(%d,%d) \"%s\" xyoff(%d,%d) bbxy(%d,%d)\n",
- __func__, (void *)info, sdir, info->bbx, info->bby, info->ulabel, xoff, yoff, bbx, bby);
- }
- }
- return;
- }
- /* handle record label sizes for one node */
- static void static_maingtk_textsizes1n(struct gml_node *node)
- {
- struct gml_p *data = NULL;
- /* calc (x,y) text size of all parts in record label */
- static_maingtk_textsizes1rl(node->rlabel);
- data = static_maingtk_textsizes1sz(node->rlabel);
- if (data == NULL) {
- /* shouldnothappen */
- return;
- }
- if (yydebug || 0) {
- printf("%s(): d is (%d,%d) versus bbxy(%d,%d)\n", __func__, data->x, data->y, node->bbx, node->bby);
- }
- /* check for use of step of bb */
- static_maingtk_textsizes1eq(node->rlabel);
- /* now position the text parts and result in the rlabel structs */
- node->bbx = data->x;
- node->bby = data->y;
- /* save copy of full size */
- node->fbbx = data->x;
- node->fbby = data->y;
- /* relocate the parts */
- static_maingtk_textsizes2rl(node->rlabel, 0, 0, 0, node->bbx, node->bby);
- data = dp_free(data);
- if (data) {
- }
- return;
- }
- /* size of one 1 html item
- * the item has fontsize, name and bitflags of type
- */
- static struct gml_p *static_maingtk_textsizes1htmlsz1item(struct gml_hitem *item)
- {
- struct gml_p *data = NULL;
- int fsz = 0;
- char *slant = NULL;
- char *weight = NULL;
- char *fn = NULL;
- cairo_surface_t *surface = NULL;
- cairo_t *crdraw = NULL;
- PangoLayout *layout = NULL;
- PangoFontDescription *desc = NULL;
- char buf[128];
- char *s = NULL;
- int w = 0;
- int h = 0;
- data = dp_calloc(1, sizeof(struct gml_p));
- if (item == NULL) {
- /* shouldnothappen */
- return (data);
- }
- if (item->bitflags.table) {
- if (yydebug || 0) {
- printf("%s(): item is a <table>\n", __func__);
- }
- if (item->table == NULL) {
- /* shouldnothappen */
- printf("%s(): item is a <table> but nil table\n", __func__);
- return (data);
- }
- /* set the size of <table> as size of this item */
- item->txsize = item->table->txsizemin;
- item->tysize = item->table->tysizemin;
- /* */
- data->x = item->txsize;
- data->y = item->tysize;
- if (yydebug || 0) {
- printf("%s(): \"%s\" has size (%d,%d) d (%d,%d)\n", __func__, "<table>", item->txsize, item->tysize, data->x, data->y);
- }
- return (data);
- }
- if (yydebug || 0) {
- printf("%s(): item->text is \"%s\"\n", __func__, item->text);
- }
- if (item->text == NULL) {
- /* shouldnothappen */
- return (data);
- }
- if (strlen(item->text) == 0) {
- /* shouldnothappen */
- return (data);
- }
- /* get fontsize */
- if (item->fontsize < 0) {
- /* not specified */
- fsz = DEFAULT_FONTSIZE_INT;
- item->fontsize = fsz;
- } else {
- /* check fontsize */
- if (item->fontsize < 5) {
- /* too small text */
- return (data);
- }
- fsz = item->fontsize;
- }
- /* italic slant */
- if (item->bitflags.i) {
- slant = "italic";
- } else {
- slant = DEFAULT_FONTSLANT;
- }
- item->fontslant = uniqstr(slant);
- /* bold weight */
- if (item->bitflags.b) {
- weight = "bold";
- } else {
- weight = DEFAULT_FONTWEIGHT;
- }
- item->fontweight = uniqstr(weight);
- /* check if fontname set */
- if (item->fontname) {
- /* at unknown fontname, default is used without warning */
- fn = item->fontname;
- } else {
- fn = DEFAULT_FONTNAME;
- }
- if (surface == NULL) {
- surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10);
- }
- /* */
- if (crdraw == NULL) {
- crdraw = cairo_create(surface);
- }
- /* */
- layout = pango_cairo_create_layout(crdraw);
- /* set the text to draw which is 0 terminated */
- pango_layout_set_text(layout, item->text, -1);
- /* create the fontname description */
- memset(buf, 0, (size_t)128);
- /* create the font name string */
- snprintf(buf, (size_t)(128 - 1), "%s %s %s %s %d", fn, slant, weight, DEFAULT_FONTCONDENSED, fsz);
- s = uniqstr(buf);
- /* */
- desc = pango_font_description_from_string(s);
- /* */
- pango_layout_set_font_description(layout, desc);
- /* */
- pango_font_description_free(desc);
- /* */
- pango_cairo_update_layout(crdraw, layout);
- /* */
- w = 0;
- h = 0;
- /* */
- pango_layout_get_size(layout, &w, &h);
- /* set text (x,y) size */
- item->txsize = (w / PANGO_SCALE);
- item->tysize = (h / PANGO_SCALE);
- /* */
- g_object_unref(G_OBJECT(layout));
- cairo_destroy(crdraw);
- crdraw = NULL;
- /* */
- cairo_surface_destroy(surface);
- surface = NULL;
- data->x = item->txsize;
- data->y = item->tysize;
- if (yydebug || 0) {
- printf("%s(): \"%s\" has size (%d,%d) d (%d,%d)\n", __func__, item->text, item->txsize, item->tysize, data->x, data->y);
- }
- return (data);
- }
- /* size of html items */
- static struct gml_p *static_maingtk_textsizes1htmlszitems(struct gml_node *node, struct gml_hl *info)
- {
- struct gml_p *data = NULL;
- struct gml_p *ditem = NULL;
- struct gml_hitem *pitem = NULL;
- struct gml_hitem *pitem2 = NULL;
- struct gml_hilist *pi = NULL;
- struct gml_hilist *pi2 = NULL;
- struct gml_hilist *sl = NULL;
- struct gml_hilist *el = NULL;
- int mxl = 0;
- int mxl2 = 0;
- int myl = 0;
- int my = 0;
- int mx = 0;
- int tof = 0;
- data = dp_calloc(1, sizeof(struct gml_p));
- if (node == NULL) {
- return (data);
- }
- if (info == NULL) {
- return (data);
- }
- if (info->il == NULL) {
- /* shouldnothappen */
- return (data);
- }
- if (yydebug || 0) {
- printf("%s(): items of node \"%s\" are:\n", __func__, node->name);
- }
- /* get size of the text elements */
- pi = info->il;
- while (pi) {
- pitem = pi->items;
- if (pitem) {
- if (pi->items->bitflags.br) {
- } else if (pi->items->bitflags.hr) {
- } else if (pi->items->bitflags.vr) {
- } else if (pi->items->bitflags.img) {
- } else if (pi->items->bitflags.table) {
- if (0) {
- printf("%s(): table bit set. todo\n", __func__);
- }
- } else {
- if (yydebug || 0) {
- printf("\"%s\"\n", pi->items->text);
- }
- ditem = static_maingtk_textsizes1htmlsz1item(pitem);
- if (ditem->x == 0 || ditem->y == 0) {
- /* zero sized text */
- }
- pitem->txsizemin = ditem->x;
- pitem->tysizemin = ditem->y;
- pitem->txsize = ditem->x;
- pitem->tysize = ditem->y;
- ditem = dp_free(ditem);
- if (ditem) {
- }
- }
- }
- pi = pi->next;
- }
- /* */
- if (yydebug || 0) {
- printf("\n");
- }
- /* determine the size of these lines */
- mx = 0;
- my = 0;
- /* */
- pi = info->il;
- tof = 0;
- while (pi) {
- /* set start/end line */
- sl = pi;
- el = pi;
- pi2 = pi;
- mxl2 = 0;
- myl = 0;
- while (pi2) {
- pitem2 = pi2->items;
- el = pi2;
- if (pi2->items) {
- if (pi2->items->bitflags.br) {
- /* newline */
- if (myl == 0) {
- /* a <br/> can have a fontsize set */
- if (pi2->items->fontsize > 0) {
- myl = pi2->items->fontsize;
- } else {
- myl = DEFAULT_FONTSIZE_INT;
- }
- }
- /* set x at start of line */
- /* mxl = 0; */
- break;
- } else if (pi2->items->bitflags.hr) {
- } else if (pi2->items->bitflags.vr) {
- } else if (pi2->items->bitflags.img) {
- } else if (pi2->items->bitflags.table) {
- if (0) {
- printf("%s(): table bit set todo\n", __func__);
- }
- } else {
- /* text x offset in this line */
- mxl2 = mxl2 + pitem2->txsize;
- if (mxl2 > mx) {
- mx = mxl2;
- }
- if (pitem2->tysize > myl) {
- myl = pitem2->tysize;
- }
- }
- }
- pi2 = pi2->next;
- }
- /* update */
- mxl = 0;
- pi2 = sl;
- while (pi2) {
- pitem2 = pi2->items;
- if (pitem2) {
- /* text x offset in this line */
- pitem2->txoff = mxl;
- mxl = mxl + pitem2->txsize;
- if (mxl > mx) {
- mx = mxl;
- }
- /* y size of this text line */
- pitem2->lysize = myl;
- /* text y offset in this line */
- pitem2->tyoff = (myl - pitem2->tysize) + tof;
- if (pi2 == el) {
- break;
- }
- }
- pi2 = pi2->next;
- }
- tof = tof + myl;
- if (tof > my) {
- my = tof;
- }
- /* continue scan other parts of item */
- if (pi2) {
- pi = pi2->next;
- } else {
- break;
- }
- }
- /* set node text (x,y) */
- node->tx = mx + 2;
- node->ty = my + 2;
- data->x = node->tx;
- data->y = node->ty;
- /* here update text x pos for br align statements if any todo */
- node->txsize = 1;
- if (yydebug || 0) {
- printf("%s(): size (%d,%d) for node \"%s\"\n", __func__, data->x, data->y, node->name);
- }
- return (data);
- }
- /* one <table> in table list */
- static struct gml_p *static_maingtk_textsizes1htmlsz1table(struct gml_node *node, struct gml_htlist *tlptr)
- {
- struct gml_p *data = NULL;
- struct gml_p *subdata = NULL;
- struct gml_p *di = NULL;
- struct gml_titem *titemptr = NULL;
- struct gml_htlist *tlptrsub = NULL;
- struct gml_tritemlist *trptr = NULL; /* list of <tr> items in this table */
- struct gml_tditem *tdiptr = NULL;
- struct gml_hilist *ilptr = NULL;
- int *tdsz = NULL;
- int ntr = 0;
- int numtd = 0;
- int ntdmax = 0;
- int trysum = 0;
- int ilmaxy = 0;
- int trxsum = 0;
- int trmax = 0;
- int tdcount = 0;
- int tdxtotal = 0;
- int tdytotal = 0;
- int wanttd = 0;
- int i = 0;
- struct gml_tditem *dummytd = NULL;
- int ystep = 0;
- int tablebgcolor = 0x00ffffff; /* white */
- data = dp_calloc(1, sizeof(struct gml_p));
- titemptr = tlptr->titem;
- if (titemptr == NULL) {
- /* shouldnothappen */
- return (data);
- }
- /* first scan the sub <table> data */ tlptrsub = titemptr->tl;
- while (tlptrsub) {
- subdata = static_maingtk_textsizes1htmlsz1table(node, tlptrsub);
- /* todo */
- subdata = dp_free(subdata);
- if (subdata) {
- }
- tlptrsub = tlptrsub->next;
- }
- /* fillcolor of this <table> */
- tablebgcolor = titemptr->bgcolor;
- trptr = titemptr->tr; /* list of <tr> items in this table */
- if (trptr == NULL) {
- /* shouldnothappen */
- return (data);
- }
- ntdmax = 0;
- ntr = 0;
- trmax = 0;
- while (trptr) {
- if (trptr->tritem == NULL) {
- /* shouldnothappen */
- return (data);
- }
- /* needed x size for this <tr> */
- trxsum = 0;
- /* <td> in <tr> */
- tdiptr = trptr->tritem->tdi;
- if (tdiptr == NULL) {
- /* shouldnothappen */
- return (data);
- }
- /* number of <td> in this <tr> */
- numtd = 0;
- ilmaxy = 0;
- while (tdiptr) {
- ilptr = tdiptr->il;
- if (ilptr == NULL) {
- /* shouldnothappen */
- return (data);
- }
- /* size of <td> */
- tdxtotal = 0;
- tdytotal = 0;
- while (ilptr) {
- di = static_maingtk_textsizes1htmlsz1item(ilptr->items);
- /* handle item size */
- /* x size of this <td> */
- if (yydebug || 0) {
- printf("%s(): item in td (%d,%d) for \"%s\"\n", __func__, di->x, di->y, ilptr->items->text);
- }
- if (di->x > tdxtotal) {
- tdxtotal = di->x;
- }
- tdytotal = tdytotal + di->y;
- trxsum = trxsum + di->x;
- tdiptr->ysize = di->y;
- /* */
- di = dp_free(di);
- if (di) {
- }
- /* next item */
- ilptr = ilptr->next;
- }
- /* set the size in this <td> */
- tdiptr->xsize = tdxtotal;
- tdiptr->ysize = tdytotal;
- if (tdiptr->ysize > ilmaxy) {
- ilmaxy = tdiptr->ysize;
- }
- if (yydebug || 0) {
- printf("%s(): td (%d,%d) size for this these td items ilmaxy=%d\n", __func__, tdiptr->xsize, tdiptr->ysize, ilmaxy);
- }
- numtd++;
- /* next <td> */
- tdiptr = tdiptr->next;
- }
- if (yydebug || 0) {
- printf("%s(): setting ysize to %d\n", __func__, ilmaxy);
- }
- /* y size in this <tr> for the <td> items */
- trptr->tritem->ysize = ilmaxy;
- /* number of <td> in this <tr> */
- trptr->tritem->numtd = numtd;
- if (numtd > ntdmax) {
- ntdmax = numtd;
- }
- /* number of <tr> statements */
- ntr++;
- /* widest <tr> */
- if (trxsum > trmax) {
- trmax = trxsum;
- }
- /* needed y size for this <td> in this <tr> */
- trysum = trysum + ilmaxy;
- /* next <tr> */
- trptr = trptr->next;
- }
- /* number of <tr> in this <table> */
- titemptr->numtr = ntr;
- titemptr->nrows = ntr;
- /* number of <td> needed for this table */
- titemptr->numtd = ntdmax;
- titemptr->ncols = ntdmax;
- /* needed y size to hold all <td> */
- titemptr->tysize = trysum;
- titemptr->tysizemin = trysum;
- /* re-scan to update the <td> size at <tr> */
- tdsz = dp_calloc(1, (sizeof(int) * ntdmax));
- /* re-scan */
- titemptr = tlptr->titem;
- trptr = titemptr->tr; /* list of <tr> items in this table */
- /* find the widest <td> at a <tr> */
- while (trptr) {
- /* <td> in <tr> */
- tdiptr = trptr->tritem->tdi;
- tdcount = 0;
- while (tdiptr) {
- if (tdiptr->xsize > tdsz[tdcount]) {
- tdsz[tdcount] = tdiptr->xsize;
- }
- tdcount++;
- /* next <td> */
- tdiptr = tdiptr->next;
- }
- /* next <tr> */
- trptr = trptr->next;
- }
- /* update the x step */
- trptr = titemptr->tr; /* list of <tr> items in this table */
- trmax = 0;
- while (trptr) {
- /* <td> in <tr> */
- tdiptr = trptr->tritem->tdi;
- trxsum = 0;
- tdcount = 0;
- while (tdiptr) {
- /* (x,y) size of <td> */
- if (yydebug || 0) {
- printf("%s(): at col=%d size (%d,%d) for this td\n", __func__, tdcount, tdiptr->xsize, tdiptr->ysize);
- }
- tdiptr->xstep = tdsz[tdcount];
- tdiptr->ystep = trptr->tritem->ysize;
- trxsum = trxsum + tdiptr->xstep;
- /* set max reached x size */
- if (trxsum > trmax) {
- trmax = trxsum;
- }
- if (yydebug || 0) {
- printf("%s(): at col=%d size (%d,%d) trmax=%d\n", __func__, tdcount, tdiptr->xstep, tdiptr->ystep, trmax);
- }
- tdcount++;
- /* next <td> */
- tdiptr = tdiptr->next;
- }
- /* next <tr> */
- trptr = trptr->next;
- }
- /* needed x size to hold all <tr> */
- titemptr->txsize = trmax;
- titemptr->txsizemin = trmax;
- /* indicate that min. size is set for this <table> */
- titemptr->sizeset = 1;
- /* set <table> (x,y) size */
- data->x = trmax;
- data->y = trysum;
- /* add dummy <td> to fill the tables */
- trptr = titemptr->tr; /* list of <tr> items in this table */
- /* find the widest <td> at a <tr> */
- while (trptr) {
- /* <td> in <tr> */
- tdiptr = trptr->tritem->tdi;
- /* number of needed <td> */
- wanttd = ntdmax;
- ystep = trptr->tritem->ysize;
- tdcount = 0;
- while (tdiptr) {
- wanttd--;
- /* set min. needed (x,y) size for <td> (x,y) size set earlier */
- tdiptr->xsizemin = tdiptr->xsize;
- tdiptr->ysizemin = tdiptr->ysize;
- tdcount++;
- /* next <td> */
- tdiptr = tdiptr->next;
- }
- if (yydebug || 0) {
- printf("%s(): <tr> has %d <td> but needs %d <td> adding %d dummy <td>\n", __func__, trptr->tritem->numtd,
- ntdmax, wanttd);
- }
- /* add the dummy <td> */
- for (i = 0; i < wanttd; i++) {
- dummytd = dp_calloc(1, sizeof(struct gml_tditem));
- /* this is a <td> with no data */
- dummytd->dummy = 1;
- /* x size depends on pos. of <td> */
- dummytd->xsize = tdsz[tdcount];
- dummytd->xstep = tdsz[tdcount];
- dummytd->xsizemin = tdsz[tdcount];
- /* y size */
- dummytd->ysize = ystep;
- dummytd->ystep = ystep;
- dummytd->ysizemin = ystep;
- /* fill color */
- dummytd->bgcolor = tablebgcolor;
- /* link in */
- if (trptr->tritem->tdi == NULL) {
- trptr->tritem->tdi = dummytd;
- trptr->tritem->tdiend = dummytd;
- } else {
- trptr->tritem->tdiend->next = dummytd;
- trptr->tritem->tdiend = dummytd;
- }
- tdcount++;
- }
- /* next <tr> */
- trptr = trptr->next;
- }
- /* ready with <td> x size data */
- tdsz = dp_free(tdsz);
- if (tdsz) {
- }
- if (yydebug || 0) {
- printf("%s(): size (%d,%d) <table> in for node \"%s\"\n", __func__, data->x, data->y, node->name);
- }
- return (data);
- }
- /* size of html tables */
- static struct gml_p *static_maingtk_textsizes1htmlsztables(struct gml_node *node, struct gml_hl *info)
- {
- struct gml_p *data = NULL;
- struct gml_p *subdata = NULL;
- struct gml_htlist *tlptr = NULL; /* list of sub table items */
- int trx = 0;
- int try = 0;
- data = dp_calloc(1, sizeof(struct gml_p));
- if (node == NULL) {
- /* shouldnothappen */
- return (data);
- }
- if (info == NULL) {
- /* shouldnothappen */
- return (data);
- }
- if (info->tl == NULL) {
- /* shouldnothappen */
- return (data);
- }
- tlptr = info->tl;
- while (tlptr) {
- subdata = static_maingtk_textsizes1htmlsz1table(node, tlptr);
- /* temp test todo */
- trx = subdata->x;
- try = subdata->y;
- subdata = dp_free(subdata);
- if (subdata) {
- }
- tlptr = tlptr->next;
- }
- data->x = trx + 2;
- data->y = try + 2;
- if (yydebug || 0) {
- printf("%s(): size (%d,%d) for node \"%s\"\n", __func__, data->x, data->y, node->name);
- }
- return (data);
- }
- /* size of html */
- static struct gml_p *static_maingtk_textsizes1htmlsz(struct gml_node *node, struct gml_hl *info)
- {
- struct gml_p *data = NULL;
- if (info->mode == 0) {
- /* html items */
- data = static_maingtk_textsizes1htmlszitems(node, info);
- } else {
- /* html tables */
- data = static_maingtk_textsizes1htmlsztables(node, info);
- }
- return (data);
- }
- /* handle html label sizes for one node */
- static void static_maingtk_textsizes1htmln(struct gml_node *node)
- {
- struct gml_p *data = NULL;
- /* preset with small value */
- node->tx = 0;
- node->ty = 0;
- node->bbx = 10;
- node->bby = 10;
- /* save copy of full size */
- node->fbbx = 10;
- node->fbby = 10;
- data = static_maingtk_textsizes1htmlsz(node, node->hlabel);
- /* for a box */
- node->bbx = data->x; /* or node->tx + 4; */
- node->bby = data->y; /* or node->ty + 4; */
- /* save copy of full size */
- node->fbbx = node->bbx;
- node->fbby = node->bby;
- if (yydebug || 0) {
- printf("%s(): size (%d,%d) for node \"%s\"\n", __func__, node->bbx, node->bby, node->name);
- }
- /* */ data = dp_free(data);
- if (data) {
- }
- return;
- }
- /* translate \n \l \r in dot string
- * todo \N and this is already done in dpif.c to check.
- */
- static char *unesc(char *str)
- {
- char *buf = NULL;
- char *p = NULL;
- char *q = NULL;
- if (str == NULL) {
- return (NULL);
- }
- if (strlen(str) == 0) {
- return (str);
- }
- if (strchr(str, '\\') == NULL) {
- /* string has no esc chars */
- return (uniqstr(str));
- }
- buf = dp_calloc(1, (strlen(str) + 1));
- p = str;
- q = buf;
- while (*p) {
- /* check for \n \l \r to change */
- if ((*p) == '\\') {
- if (*(p + 1) == 'n' || *(p + 1) == 'l' || *(p + 1) == 'r') {
- (*q) = '\n';
- q++;
- p++;
- p++;
- } else {
- /* copy other esc char */
- (*q) = (*p);
- p++;
- q++;
- (*q) = (*p);
- p++;
- q++;
- }
- } else {
- /* regular char to copy */
- (*q) = (*p);
- q++;
- p++;
- }
- }
- p = uniqstr(buf);
- buf = dp_free(buf);
- if (buf) {
- }
- return (p);
- }
- /* get size of one char *string */
- static struct gml_p *static_maingtk_textsizes1str(char *str)
- {
- struct gml_p *ret = NULL;
- cairo_surface_t *surface = NULL;
- cairo_t *crdraw = NULL;
- PangoLayout *layout = NULL;
- PangoFontDescription *desc = NULL;
- int w = 0;
- int h = 0;
- char buf[128];
- char *s = NULL;
- /* name of font to use, example "Sans" */
- const char *default_fontname = DEFAULT_FONTNAME;
- /* name of slant to use, example "Italic", "Oblique", "Roman" */
- const char *default_fontslant = DEFAULT_FONTSLANT;
- /* name of weight to use, example "Bold", "Book", "Light", "Medium", "Semi-bold", "Ultra-light" */
- const char *default_fontweight = DEFAULT_FONTWEIGHT;
- /* name of condensed to use, example "Semi-Condensed", "Condensed" */
- const char *default_fontcondensed = DEFAULT_FONTCONDENSED;
- /* font size to use, example "10", "18", "20" etc. */
- const char *default_fontsize = DEFAULT_FONTSIZE;
- /* return size in this */
- ret = (struct gml_p *)dp_calloc(1, sizeof(struct gml_p));
- if (str == NULL) {
- /* shouldnothappen */
- printf("%s(): nil str\n", __func__);
- return (ret);
- }
- if (strlen(str) == 0) {
- /* shouldnothappen */
- printf("%s(): empty str\n", __func__);
- return (ret);
- }
- /* calculate the text area */
- if (surface == NULL) {
- surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10);
- }
- /* */
- if (crdraw == NULL) {
- crdraw = cairo_create(surface);
- }
- /* */
- layout = pango_cairo_create_layout(crdraw);
- /* set the text to draw which is 0 terminated */
- pango_layout_set_text(layout, str, -1);
- /* create the fontname description */
- memset(buf, 0, (size_t)128);
- /* name of font to use */
- default_fontname = uniqstr((char *)DEFAULT_FONTNAME);
- /* check if node has a specified font slant */
- default_fontslant = uniqstr((char *)DEFAULT_FONTSLANT);
- /* check if node has a specified font weight */
- default_fontweight = uniqstr((char *)DEFAULT_FONTWEIGHT);
- /* check if node has a specified font size */
- default_fontsize = uniqstr((char *)DEFAULT_FONTSIZE);
- /* create the font name string */
- snprintf(buf, (size_t)(128 - 1), "%s %s %s %s %s",
- default_fontname, default_fontslant, default_fontweight, default_fontcondensed, default_fontsize);
- /* copy string buffer */
- s = uniqstr(buf);
- /* */
- desc = pango_font_description_from_string(s);
- /* */
- pango_layout_set_font_description(layout, desc);
- /* */
- pango_font_description_free(desc);
- /* */
- pango_cairo_update_layout(crdraw, layout);
- /* */
- w = 0;
- h = 0;
- /* */
- pango_layout_get_size(layout, &w, &h);
- /* */
- g_object_unref(G_OBJECT(layout));
- /* */
- if (option_gdebug > 1 || 0) {
- printf("%s(): size (%d,%d) for string \"%s\"\n", __func__, (w / PANGO_SCALE), (h / PANGO_SCALE), str);
- fflush(stdout);
- }
- ret->x = (w / PANGO_SCALE);
- ret->y = (h / PANGO_SCALE);
- /* clear the draw context etc */
- if (layout) {
- layout = NULL;
- }
- if (crdraw) {
- cairo_destroy(crdraw);
- crdraw = NULL;
- }
- if (surface) {
- cairo_surface_destroy(surface);
- surface = NULL;
- }
- return (ret);
- }
- /*zzz
- * update the (x,y) size of text in the nodes
- *
- * a GTK font pattern. These have the syntax
- * fontname [properties] [fontsize]
- *
- * where fontname is the family name,
- * properties is a list of property values separated by spaces,
- * and fontsize is the point size.
- * The properties that you may specify for GTK font patterns are as follows:
- * Slant properties: ‘Italic’ or ‘Oblique’. If omitted, the default (roman) slant is implied.
- * Weight properties: ‘Bold’, ‘Book’, ‘Light’, ‘Medium’, ‘Semi-bold’, or ‘Ultra-light’. If omitted, ‘Medium’ weight is implied.
- * Width properties: ‘Semi-Condensed’ or ‘Condensed’. If omitted, a default width is used.
- * Here are some examples of GTK font patterns:
- * Monospace 12
- * Monospace Bold Italic 12
- *
- * there are nodes with labels whicj is a piece of text on display
- * and nodes with a record type with multiple small text to layout
- * in multiple steps for the different fields.
- * if option labels is 0 then no label text is draw
- */
- static void static_maingtk_textsizes(void)
- {
- struct gml_p *sz = NULL;
- int txname = 0;
- int tyname = 0;
- int bbxname = 0;
- int bbyname = 0;
- struct gml_ellist *elptr = NULL;
- /* */
- struct gml_nlist *nl = NULL;
- int changed = 0;
- /* only once determine edge label sizes */
- if (maingraph->elsizes == 0) {
- if (maingraph->ellist) {
- /* edges with edge labels */
- elptr = maingraph->ellist;
- while (elptr) {
- if (elptr->eledge) {
- /* set size of edge label */
- sz = static_maingtk_textsizes1str(elptr->eledge->elabel);
- elptr->eledge->tx = sz->x;
- elptr->eledge->ty = sz->y;
- sz = (struct gml_p *)dp_free((struct gml_p *)sz);
- if (sz) {
- }
- }
- elptr = elptr->next;
- }
- }
- /* all ready */
- maingraph->elsizes = 1;
- }
- if (maingraph->nodesizes != 0) {
- /* all done already */
- return;
- }
- /* scan the regular node list */
- changed = 0;
- nl = maingraph->nodelist;
- while (nl) {
- if (nl->node) {
- /* check the un-set */
- if (nl->node->txsize == 0 || 0) {
- changed++;
- if (nl->node->dummy) {
- /* dummynode has no text */
- nl->node->tx = 0;
- nl->node->ty = 0;
- nl->node->bbx = 0;
- nl->node->bby = 0;
- nl->node->txsize = 1; /* text size is set */
- } else {
- /* first get size of node name */
- if (nl->node->name == NULL) {
- /* shouldnothapen */
- nl->node->name = uniqstr((char *)"fixme-nil-node-name");
- }
- /* get size of node name */
- sz = static_maingtk_textsizes1str(nl->node->name);
- txname = sz->x;
- tyname = sz->y;
- /* for a box */
- bbxname = txname + 4;
- bbyname = tyname + 4;
- sz = (struct gml_p *)dp_free((struct gml_p *)sz);
- if (sz) {
- }
- /* change esc chars if any */
- nl->node->nlabel = unesc(nl->node->nlabel);
- sz = static_maingtk_textsizes1str(nl->node->nlabel);
- /* set label text size */
- nl->node->tx = sz->x;
- nl->node->ty = sz->y;
- nl->node->ftx = sz->x;
- nl->node->fty = sz->y;
- sz = (struct gml_p *)dp_free((struct gml_p *)sz);
- if (sz) {
- }
- /* for a box */
- nl->node->bbx = nl->node->tx + 4;
- nl->node->bby = nl->node->ty + 4;
- /* full sized copy */
- nl->node->fbbx = nl->node->bbx;
- nl->node->fbby = nl->node->bby;
- if (option_gdebug > 1 || 0) {
- printf("%s(): hlabel=%p done=%d and rlabel=%p done=%d\n", __func__,
- (void *)nl->node->hlabel, nl->node->hlabeldone, (void *)nl->node->rlabel, nl->node->rlabeldone);
- }
- /* html label or record label */
- if ((nl->node->hlabel != NULL) && (nl->node->hlabeldone == 0)) {
- /* html label */
- static_maingtk_textsizes1htmln(nl->node);
- nl->node->hlabeldone = 1;
- } else {
- /* record node label */
- if ((nl->node->rlabel != NULL) && (nl->node->rlabeldone == 0)) {
- static_maingtk_textsizes1n(nl->node);
- nl->node->rlabeldone = 1;
- }
- }
- if (option_nnames == 1) {
- /* use node names instead of labels and do not draw r/h style labels */
- nl->node->drawrh = 0;
- nl->node->tx = txname;
- nl->node->ty = tyname;
- /* for a box */
- nl->node->bbx = bbxname;
- nl->node->bby = bbyname;
- } else {
- nl->node->drawrh = 1;
- }
- /* label==0 then do not draw text label of a node and set small size */
- if (option_labels == 0) {
- nl->node->tx = 10;
- nl->node->ty = 10;
- /* for a box */
- nl->node->bbx = nl->node->tx + 4;
- nl->node->bby = nl->node->ty + 4;
- /* keep fbbx and fbby intact */
- }
- nl->node->txsize = 1; /* text size is set */
- }
- } /* txsize */
- } /* node */
- /* next node in nodelist */
- nl = nl->next;
- }
- if (changed == 0 || 0) {
- maingraph->nodesizes = 1;
- }
- return;
- }
- /* do final (x,y) of nodes/edges for mode 1 todo should use absx */
- static void finalxy1(struct gml_graph *g)
- {
- struct gml_nlist *lnl = NULL;
- int hw = 0;
- int xoff = 0;
- int yoff = 0;
- int i = 0;
- int ecount = 0;
- int tt = 0; /* only for a test absx,y is relative */
- /* x positioning */
- make_posnodes(maingraph);
- maxx = 0;
- xoff = 0;
- /* scan hor. to adjust the x positions. */
- for (i = 0; i < (g->widestnnodes + 1); i++) {
- /* x spacing between the hor. levels */
- xoff = xoff + xspacing;
- /* determine half-way of the xpos. */
- if (g->wpos[i] == 0) {
- /* if only dummy nodes */
- hw = xspacing / 2;
- } else {
- hw = (g->wpos[i] / 2);
- }
- /* update with current x */
- hw = hw + xoff;
- lnl = g->posnodes[i];
- /* scan the nodes at this x pos. */
- while (lnl) {
- /* center the node around the half-way */
- if (tt) {
- /* test */
- lnl->node->finx = lnl->node->absx;
- } else {
- lnl->node->finx = (hw - (lnl->node->bbx / 2));
- }
- if ((lnl->node->finx + lnl->node->bbx) > maxx) {
- maxx = (lnl->node->finx + lnl->node->bbx);
- }
- lnl = lnl->next;
- }
- lnl = g->posnodes[i];
- /* scan the nodes at this x pos. */
- while (lnl) {
- /* center the node around the half-way */
- lnl->node->lx0 = xoff;
- lnl->node->lx1 = xoff + g->wpos[i];
- /* x size of level */
- lnl->node->lxsize = g->wpos[i];
- lnl = lnl->next;
- }
- /* x spacing between the hor. levels */
- xoff = xoff + xspacing;
- /* x to next pos. */
- xoff = xoff + g->wpos[i];
- }
- clear_posnodes_r(maingraph);
- /* y positioning */
- make_levelnodes(maingraph);
- maxy = 0;
- yoff = 0;
- /* number of edges between level n and n+1 */
- g->nume = (int *)dp_calloc(1, (maingraph->maxlevel + 1) * sizeof(int));
- /* scan vert. to adjust the y positions. */
- for (i = 0; i < (maingraph->maxlevel + 1); i++) {
- /* y spacing between the vert. levels */
- yoff = yoff + (yspacing / 1);
- /* determine half-way of the ypos. */
- if (g->hpos[i] == 0) {
- /* if only dummy nodes */
- hw = (yspacing / 2);
- } else {
- hw = (g->hpos[i] / 2);
- }
- /* update with current y */
- hw = hw + yoff;
- lnl = g->levelnodes[i];
- ecount = 0;
- /* scan the nodes at this y pos. */
- while (lnl) {
- /* set start, end of y level */
- lnl->node->ly0 = yoff;
- /* used in drawing */
- lnl->node->ly1 = (yoff + g->hpos[i]);
- /* size of level y */
- lnl->node->lysize = g->hpos[i];
- /* center the node around the half-way */
- if (tt) {
- /* test */
- lnl->node->finy = lnl->node->absy;
- } else {
- lnl->node->finy = (hw - (lnl->node->bby / 2));
- }
- /* update drawing max y pos used */
- if ((lnl->node->finy + lnl->node->bby) > maxy) {
- maxy = (lnl->node->finy + lnl->node->bby);
- }
- /* give dummy nodes a vertical size of the level */
- if (lnl->node->dummy) {
- lnl->node->bby = g->hpos[i];
- /* if only dummy nodes at level, use spacing */
- if (g->hpos[i] == 0) {
- lnl->node->bby = yspacing;
- }
- }
- /* number of edges between level n and n+1 */
- ecount = (ecount + lnl->node->outdegree);
- lnl = lnl->next;
- }
- /* number of edges between level n and n+1 */
- g->nume[i] = ecount;
- /* y spacing between the vert. levels */
- yoff = yoff + (yspacing / 1);
- /* yspacing depends on number of edges at this level
- * turned off because this add too much y-spacing
- * yoff = yoff + (ecount * 3);
- */
- /* yspacing depends on number of crossing edges at this level
- * this has increasing y effect between levels
- */
- if (g->numce) {
- yoff = yoff + (1 * (g->numce[i] / 8));
- }
- /* y to next pos. */
- yoff = yoff + g->hpos[i];
- }
- clear_levelnodes_r(maingraph);
- /* clear number of edges between level n and n+1 */
- clear_nume_r(maingraph);
- return;
- }
- /* for pos2.c which does set finx,finy */
- static void finalxy2(struct gml_graph *g)
- {
- struct gml_nlist *lnl = NULL;
- int my = 0;
- maxx = 0;
- maxy = 0;
- /* adjust for the y size of single nodes */
- if (g->nsinglenodes) {
- my = 0;
- lnl = maingraph->singlenodelist;
- while (lnl) {
- if (lnl->node->bby > my) {
- my = lnl->node->bby;
- }
- lnl = lnl->next;
- }
- /* update level data for single nodes */
- lnl = maingraph->singlenodelist;
- while (lnl) {
- lnl->node->ly0 = 0;
- lnl->node->ly1 = my;
- lnl = lnl->next;
- }
- } else {
- /* no singlenodes, start at top of drawing */
- my = 0;
- }
- /* determine max. x pos in use */
- lnl = maingraph->nodelist;
- while (lnl) {
- /* adjust the non-singlenodes down */
- if (lnl->node->indegree || lnl->node->outdegree) {
- lnl->node->finy = lnl->node->finy + my;
- lnl->node->ly0 = lnl->node->ly0 + my;
- lnl->node->ly1 = lnl->node->ly1 + my;
- }
- if ((lnl->node->finx + lnl->node->bbx) > maxx) {
- maxx = lnl->node->finx + lnl->node->bbx;
- }
- /* update drawing max y pos used */
- if ((lnl->node->finy + lnl->node->bby) > maxy) {
- maxy = (lnl->node->finy + lnl->node->bby);
- }
- lnl = lnl->next;
- }
- return;
- }
- /* for pos.c which does set absx,absy */
- static void finalxy3(struct gml_graph *g)
- {
- struct gml_nlist *lnl = NULL;
- /* recalc drawing size */
- maxx = 0;
- maxy = 0;
- if (g == NULL) {
- /* shouldnothappen */
- return;
- }
- /* determine max. x pos in use */
- lnl = maingraph->nodelist;
- while (lnl) {
- /* copy abs to fin */
- lnl->node->finx = lnl->node->absx;
- lnl->node->finy = lnl->node->absy;
- if ((lnl->node->finx + lnl->node->bbx) > maxx) {
- maxx = lnl->node->finx + lnl->node->bbx;
- }
- /* update drawing max y pos used */
- if ((lnl->node->finy + lnl->node->bby) > maxy) {
- maxy = (lnl->node->finy + lnl->node->bby);
- }
- lnl = lnl->next;
- }
- return;
- }
- /* for pos.c which does set absx,absy */
- static void finalxy4(struct gml_graph *g)
- {
- struct gml_nlist *lnl = NULL;
- printf("%s(): testing mode now\n", __func__);
- /* recalc drawing size */
- maxx = 0;
- maxy = 0;
- if (g == NULL) {
- /* shouldnothappen */
- return;
- }
- /* determine max. x pos in use */
- lnl = maingraph->nodelist;
- while (lnl) {
- /* copy abs to fin */
- lnl->node->finx = lnl->node->absx;
- lnl->node->finy = lnl->node->absy;
- if ((lnl->node->finx + lnl->node->bbx) > maxx) {
- maxx = lnl->node->finx + lnl->node->bbx;
- }
- /* update drawing max y pos used */
- if ((lnl->node->finy + lnl->node->bby) > maxy) {
- maxy = (lnl->node->finy + lnl->node->bby);
- }
- lnl = lnl->next;
- }
- return;
- }
- static void finalxy(struct gml_graph *g)
- {
- struct gml_nlist *lnl = NULL;
- int xpos = 0;
- int my = 0;
- /* depends on positioning modus */
- /* if set use priority algorithm for placement otherwise brandes and kopf */
- if (option_priority) {
- }
- switch (postype) {
- case 1:
- finalxy1(g);
- break;
- case 2:
- finalxy2(g);
- break;
- case 3:
- /* only raw positioning */
- finalxy3(g);
- break;
- case 4: /* brandes kopf algorithm */
- finalxy4(g);
- break;
- default:
- printf("%s(): shouldnothappen\n", __func__);
- finalxy1(g);
- break;
- }
- /* position level 0, single nodes if any */
- if (g->nsinglenodes) {
- my = 0;
- xpos = xspacing;
- lnl = g->singlenodelist;
- while (lnl) {
- lnl->node->finx = xpos;
- lnl->node->finy = 0;
- /* position single nodes at level 0, just next to each other */
- xpos = xpos + lnl->node->bbx + xspacing;
- if (lnl->node->bby > my) {
- my = lnl->node->bby;
- }
- if (xpos > maxx) {
- maxx = xpos;
- }
- lnl = lnl->next;
- }
- }
- return;
- }
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* XPM */
- static const char *data_visualization_1_xpm[] = {
- "50 50 119 2",
- " c #FFFFFF",
- ". c #ECECEC",
- "+ c #B1B1B1",
- "@ c #808080",
- "# c #6C6C6C",
- "$ c #898989",
- "% c #C0C0C0",
- "& c #F6F6F6",
- "* c #BBBBBB",
- "= c #1C1C1C",
- "- c #000000",
- "; c #474747",
- "> c #DADADA",
- ", c #222222",
- "' c #DFDFDF",
- ") c #606060",
- "! c #C7C7C7",
- "~ c #B9B9B9",
- "{ c #383838",
- "] c #666666",
- "^ c #FCFCFC",
- "/ c #F7F7F7",
- "( c #E5E5E5",
- "_ c #D9D9D9",
- ": c #F1F1F1",
- "< c #E4E4E4",
- "[ c #F2F2F2",
- "} c #7F7F7F",
- "| c #989898",
- "1 c #B6B6B6",
- "2 c #E9E9E9",
- "3 c #7E7E7E",
- "4 c #767676",
- "5 c #E3E3E3",
- "6 c #6D6D6D",
- "7 c #B2B2B2",
- "8 c #ACACAC",
- "9 c #EBEBEB",
- "0 c #3D3D3D",
- "a c #2E2E2E",
- "b c #848484",
- "c c #C2C2C2",
- "d c #979797",
- "e c #787878",
- "f c #BFBFBF",
- "g c #C6C6C6",
- "h c #EAEAEA",
- "i c #F9F9F9",
- "j c #161616",
- "k c #838383",
- "l c #5F5F5F",
- "m c #FDFDFD",
- "n c #EFEFEF",
- "o c #F8F8F8",
- "p c #828282",
- "q c #ADADAD",
- "r c #424242",
- "s c #9A9A9A",
- "t c #CECECE",
- "u c #9F9F9F",
- "v c #818181",
- "w c #FAFAFA",
- "x c #F0F0F0",
- "y c #868686",
- "z c #535353",
- "A c #555555",
- "B c #939393",
- "C c #AEAEAE",
- "D c #D1D1D1",
- "E c #878787",
- "F c #777777",
- "G c #404040",
- "H c #CFCFCF",
- "I c #A0A0A0",
- "J c #A1A1A1",
- "K c #3B3B3B",
- "L c #D0D0D0",
- "M c #757575",
- "N c #565656",
- "O c #585858",
- "P c #5A5A5A",
- "Q c #FBFBFB",
- "R c #D8D8D8",
- "S c #B4B4B4",
- "T c #C1C1C1",
- "U c #DEDEDE",
- "V c #636363",
- "W c #DBDBDB",
- "X c #999999",
- "Y c #858585",
- "Z c #A7A7A7",
- "` c #494949",
- " . c #8C8C8C",
- ".. c #8E8E8E",
- "+. c #C8C8C8",
- "@. c #8A8A8A",
- "#. c #FEFEFE",
- "$. c #B8B8B8",
- "%. c #ABABAB",
- "&. c #B5B5B5",
- "*. c #C5C5C5",
- "=. c #9D9D9D",
- "-. c #5D5D5D",
- ";. c #B7B7B7",
- ">. c #353535",
- ",. c #BEBEBE",
- "'. c #656565",
- "). c #EDEDED",
- "!. c #BCBCBC",
- "~. c #262626",
- "{. c #E0E0E0",
- "]. c #F3F3F3",
- "^. c #454545",
- "/. c #BDBDBD",
- "(. c #4B4B4B",
- "_. c #DDDDDD",
- ":. c #323232",
- "<. c #6E6E6E",
- "[. c #A8A8A8",
- " ",
- " ",
- " ",
- " . + @ # $ % & ",
- " * = - - - - - ; > ",
- " * - - - - - - - - , ' ",
- " . = - - ) ! > ~ { - - ] ^ ",
- " + - - ) / ( , - - _ : < [ ",
- " } - - ! | - - 1 2 3 - - - 4 5 ",
- " 6 - - > 7 - - 8 9 0 - - - - - a 5 ",
- " $ - - ~ b - - c d - - - - - - - e ",
- " f - - { ( g - - - h i j - - - - - - - - [ ",
- " & ; - - , | 7 k - - - l m n - - - - - - - - - ( ",
- " > , - - - - - - - - - | ^ o = - - - - - - - - [ ",
- " ' ] - - - - - l - - - | ^ ^ ] - - - - - - - p ",
- " ^ _ 1 q c h m | - - - | ^ ^ d - - - - - - - r 2 ",
- " ^ | - - - | ^ ^ d - - - ] = - j s . ",
- " ^ | - - - d ^ i t u v v u t w ^ d - - - d ^ i x w ",
- " ^ | - - - y z - - - - - - A y - - - d ^ ",
- " m | - - - - - - - - - - - - - - B ^ ",
- " ^ y - - - 0 C D D q 0 - - - E ^ ",
- " w z - - F [ [ 4 - - A w ",
- " t - - G [ [ 0 - - H ",
- " u - - C q - - I ",
- " v - - D D - - p ",
- " v - - D D - - p ",
- " u - - q 8 - - J ",
- " t - - 0 [ : K - - L ",
- " w A - - 4 [ : M - - N w ",
- " ^ E - - - 0 q D D 8 K - - - E ^ ",
- " m | - - - - - - - - - - - - - - B ^ ",
- " ^ | - - - y O - - - - - - P y - - - | ^ ",
- " ^ | - - - d ^ Q D 4 - - 4 D Q ^ d - - - | ^ ",
- " m | - - - B ^ + - - + m | - - - B ^ ",
- " ^ R S q T 2 m | - - - | ^ + - - + ^ | - - - | m 2 T q S R ^ ",
- " U V - - - - - l - - - | ^ + - - + ^ | - - - l - - - - - V ' ",
- " > , - - - - - - - - - | ^ + - - + ^ | - - - - - - - - - , W ",
- " & ; - - , X 7 Y - - - l m Z - - Z m l - - - Y 7 X , - - ` / ",
- " f - - { ( ! - - - 2 / .- - - - ../ 2 - - - +. ( { - - % ",
- " $ - - ~ b - - c m @.- - - - - - .#. T - - Y $.- - @. ",
- " 6 - - > 7 - - 8 > - - - - - - - - W %.- - 7 _ - - 6 ",
- " } - - ! d - - 1 Z - - - - - - - - q &.- - s *.- - v ",
- " 7 - - ) / < = - - > =.- - - - - - - - Z R - - , ( & -.- - 7 ",
- " . = - - l g _ ;.>.- - ] ^ ,.- - - - - - - - ,. ^ '.- - { ~ _ *.-.- - , ). ",
- " !.- - - - - - - - ~.{. ].^.- - - - - - ^.]. ' , - - - - - - - - ,. ",
- " /., - - - - - (.W _.:.- - - - >._. W ` - - - - - , ,. ",
- " ).7 v # @.% / x Z <.<.[.x / % @.# p 7 ). ",
- " ",
- " ",
- " "
- };
- #endif
- /* show about with ok button
- * Android devices are “tyrants” says RMS
- * https://www.gnu.org/philosophy/android-and-users-freedom.html
- * So, Stallman was right ... again
- * https://www.reddit.com/r/StallmanWasRight/
- * https://letmegooglethat.com/?q=stallman+was+right+again
- * This is not a android program and does not need camera, microphone, location, notifications or other anti-features
- */
- static void show_about_bare(void)
- {
- GtkWidget *dialog = NULL;
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- GdkPixbuf *xpmdata = NULL;
- #endif
- int buflen = 0;
- char *buf = NULL;
- char *pbuf = NULL;
- char *text0 = "This is a GML (Graph-Markup_Language) graph viewer program.\n"
- "This program is free to share, copy, use, modify or fork.\n"
- "This program does not have network telemetry or creates files.\n"
- "This program does not want access to camera, microphone or location.\n"
- "See gml4gtk at sourceforge.net\nemail: mooigraph AT gmail.com\n";
- #ifdef WIN32
- /* Linux software does not need a key but windows users seeem to need a product key. */
- char *text1 = "Product key: B2X2W-DY9D9-YBP8R-G77WC-QB3QM";
- #else
- char *text1 = "Product Key: GNU-GPL-FREE-SOFT-WARE";
- #endif
- #if (GTK_HAVE_API_VERSION_4== 1)
- /* a magyar étel finom és Ilona tökéletes */
- const char *artist[] = { "ILona and her daughter from Hungary", NULL };
- #endif
- buflen = 512;
- buf = dp_calloc(1, buflen);
- /* reserve the last 0x00 space */
- buflen--;
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- dialog = gtk_about_dialog_new();
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1)
- gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(dialog), PACKAGE_NAME);
- #endif
- #if (GTK_HAVE_API_VERSION_3 == 1)
- gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), PACKAGE_NAME);
- #endif
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* todo it seems this is depreciated. */
- xpmdata = gdk_pixbuf_new_from_xpm_data(data_visualization_1_xpm);
- gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), xpmdata);
- gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), PACKAGE_VERSION);
- gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), "Copyright is GNU GPL Version 3+, see http://www.gnu.org/");
- #endif
- snprintf(buf, (size_t)(buflen), "%sCompiled on %s\n", text0, COMPILE_DATE);
- pbuf = buf + (int)(strlen(buf));
- /* */
- snprintf(pbuf, (size_t)(buflen - (int)(strlen(buf)) - 1), "%s\n", text1);
- pbuf = buf + (int)(strlen(buf));
- snprintf(pbuf, (size_t)(buflen - (int)(strlen(buf)) - 1), "compiled with gtk %d.%d.%d glib %d.%d.%d pango %s cairo %s\n",
- GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION,
- GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION, PANGO_VERSION_STRING, CAIRO_VERSION_STRING);
- pbuf = buf + (int)(strlen(buf));
- /* */
- /* pango_version_string() and pango_version_string() are the versions at compile time, not run time */
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- snprintf(pbuf, (size_t)(buflen - (int)(strlen(buf)) - 1), "running with gtk %d.%d.%d glib %d.%d.%d pango %s cairo %s\n",
- gtk_major_version, gtk_minor_version, gtk_micro_version,
- glib_major_version, glib_minor_version, glib_micro_version, pango_version_string(), cairo_version_string());
- #endif
- #if (GTK_HAVE_API_VERSION_4 == 1)
- snprintf(pbuf, (size_t)(buflen - (int)(strlen(buf)) - 1), "running with gtk %u.%u.%u glib %d.%d.%d pango %s cairo %s\n",
- gtk_get_major_version(), gtk_get_minor_version(), gtk_get_micro_version(),
- (int)glib_major_version, (int)glib_minor_version, (int)glib_micro_version, pango_version_string(),
- cairo_version_string());
- #endif
- pbuf = buf + (int)(strlen(buf));
- snprintf(pbuf, (size_t)(buflen - (int)(strlen(buf)) - 1), "running with zlib version %s\n", zlibVersion());
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), buf);
- gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), PACKAGE_URL);
- /* suppress warning */
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(dialog);
- #endif
- #if (GTK_HAVE_API_VERSION_4== 1)
- dialog = gtk_about_dialog_new();
- gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), PACKAGE_STRING);
- gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), PACKAGE_URL);
- gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), PACKAGE_URL);
- gtk_about_dialog_set_license_type(GTK_ABOUT_DIALOG(dialog), GTK_LICENSE_GPL_3_0);
- gtk_about_dialog_set_system_information(GTK_ABOUT_DIALOG(dialog), buf);
- gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog), artist);
- /* suppress warning */
- gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(mainwindow1));
- gtk_widget_show(dialog);
- #endif
- buf = dp_free(buf);
- if (buf) {
- }
- return;
- }
- #if (GTK_HAVE_API_VERSION_2 == 1) || (GTK_HAVE_API_VERSION_3 == 1)
- /* show about with ok button */
- static void show_about(GtkWidget * widget, gpointer data)
- {
- if (widget) {
- }
- if (data) {
- }
- show_about_bare();
- return;
- }
- #endif
- /* end */
|