| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819 | /** LaGUI: A graphical application framework.* Copyright (C) 2022-2023 Wu Yiming** 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/>.*/#ifdef LA_USE_GLES#define NANOVG_GLES3_IMPLEMENTATION#else#define NANOVG_GL3_IMPLEMENTATION#endif#include "la_5.h"#include <stdio.h>#include <stdlib.h>#include <math.h>#include <time.h>#ifdef __linux__#include <execinfo.h>#include <signal.h>#include <sys/time.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xos.h>#include <X11/keysymdef.h>#include <X11/XKBlib.h>#include <X11/extensions/XInput.h>#include <X11/extensions/XInput2.h>#include <X11/extensions/Xfixes.h>#include <X11/extensions/Xrandr.h>#include <X11/Xcursor/Xcursor.h>#include <X11/cursorfont.h>#include <GL/glx.h>#endif#ifdef _WIN32#include <GL/wglew.h>#include <GL/wgl.h>#include <shellscalingapi.h>#endifLA MAIN;extern tnsMain *T;int deb = 0;laOperator *DEB;laColumn *DEBUG_C;#ifdef _WIN32#define LA_GUI_WNDCLASS_NAME L"NUL4_GUI_CLASS"#else#define LA_GUI_WNDCLASS_NAME "NUL4_GUI_CLASS"#endif#ifdef __linux__typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);\typedef void (*glXSwapIntervalEXTProc)(Display *dpy, GLXDrawable drawable, int interval);glXCreateContextAttribsARBProc glXCreateContextAttribsF;glXSwapIntervalEXTProc glXSwapIntervalEXTF;#endif#ifdef __linux__static void la_PrintWacomValuators(Display *display, XIAnyClassInfo **classes, int num_classes){    int i;    for (i = 0; i < num_classes; i++) {        if (classes[i]->type == XIValuatorClass) {            XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i];            logPrint("        Valuator %d: '%s'\n", v->number, (v->label) ?  XGetAtomName(display, v->label) : "No label");            logPrint("            Range: %f - %f\n", v->min, v->max);            logPrint("            Resolution: %d units/m\n", v->resolution);            logPrint("            Mode: %s\n", v->mode == XIModeAbsolute ? "absolute": "relative");            if (v->mode == XIModeAbsolute) logPrint("            Current value: %f\n", v->value);        }    }}static void la_RegisterWacomEventMasks(Display *display, int deviceid, real* max_pressure) {	XIDeviceInfo *info, *dev;	int i, ndevices;	dev = XIQueryDevice(display, deviceid, &ndevices);    XIEventMask *mask=memAcquireSimple(sizeof(XIEventMask));    mask->deviceid = deviceid;    mask->mask_len = XIMaskLen(XI_RawMotion);    mask->mask=memAcquireSimple(mask->mask_len);    memset(mask->mask, 0, mask->mask_len);	XISetMask(mask->mask, XI_RawMotion);    XISelectEvents(display, DefaultRootWindow(display), mask, 1);    int FoundMax=0;    for (i = 0; i < dev->num_classes; i++) {        if (dev->classes[i]->type == XIValuatorClass) {            XIValuatorClassInfo *v = (XIValuatorClassInfo*)dev->classes[i];            if(v->number==2){ *max_pressure=v->max; FoundMax=1; break; }        }    }    if(!FoundMax){*max_pressure=65535;}	logPrint("    Device Name: '%s' (%d)\n", dev->name, dev->deviceid);	//la_PrintWacomValuators(display, dev->classes, dev->num_classes);    XIFreeDeviceInfo(dev);}int la_DeviceProbablyHasPressure(XIDeviceInfo* dev){    int axis=0;    for (int i = 0; i < dev->num_classes; i++) {        if (dev->classes[i]->type == XIValuatorClass){ axis++; }    }    return axis>=3;}#define LA_G_STYLUS(dev) \    (la_DeviceProbablyHasPressure(dev)&&(!MAIN.WacomDeviceStylus))#define LA_G_ERASER \    (!MAIN.WacomDeviceEraser)void la_ScanWacomDevices(Display *display, int deviceid){    XIDeviceInfo *info, *dev;    int ndevices;    int i; char * word;    int _event, _error;    if (!XQueryExtension(MAIN.dpy, "XInputExtension", &MAIN.xi_opcode, &_event, &_error)) {        logPrint("X Input extension not available, wacom pressure events are not available.\n"); return;    }    info = XIQueryDevice(display, deviceid, &ndevices);    for(i = 0; i < ndevices; i++) {        dev = &info[i]; strToLower(dev->name);        if (strstr(dev->name, "pen pen")){ if(LA_G_STYLUS(dev)) MAIN.WacomDeviceStylus = dev->deviceid; } // some wacom tablets "wacom bamboo connect pen pen"        elif (strstr(dev->name, "stylus pen")){ if(LA_G_STYLUS(dev)) MAIN.WacomDeviceStylus = dev->deviceid; } // some huion ones "HUION 256C PEN STYLUS Pen"        int is_ipts=0; if(strstr(dev->name, "ipts")){ is_ipts=1; }        word = strtok (dev->name," ");        while (1) {            word = strtok (NULL, " "); if (!word) break;            if (strcmp("stylus", word) == 0){ if(LA_G_STYLUS(dev)) MAIN.WacomDeviceStylus = dev->deviceid; }// wacom            elif (strcmp("eraser", word) == 0){ if(LA_G_ERASER) MAIN.WacomDeviceEraser = dev->deviceid; }// wacom            elif (is_ipts && strcmp("pen", word) == 0){ if(LA_G_STYLUS(dev)) MAIN.WacomDeviceStylus = dev->deviceid; }// surface ipts            elif (is_ipts && strcmp("eraser", word) == 0){ if(LA_G_ERASER) MAIN.WacomDeviceEraser = dev->deviceid; }// surface ipts            elif (strcmp("pen", word) == 0){ if(LA_G_STYLUS(dev)) MAIN.WacomDeviceStylus = dev->deviceid; }// generic pen        }    }    if(MAIN.WacomDeviceStylus || MAIN.WacomDeviceEraser){        logPrintNew("Found wacom devices:\n");        if(MAIN.WacomDeviceStylus) la_RegisterWacomEventMasks(display, MAIN.WacomDeviceStylus,&MAIN.StylusMaxPressure);        if(MAIN.WacomDeviceEraser) la_RegisterWacomEventMasks(display, MAIN.WacomDeviceEraser,&MAIN.EraserMaxPressure);	}else{        logPrintNew("No wacom pen device connected.\n");	}    XIFreeDeviceInfo(info);}void laHideCursor(){    if(!MAIN.CurrentWindow) return; XFixesHideCursor(MAIN.dpy, MAIN.CurrentWindow->win);}void laShowCursor(){    if(!MAIN.CurrentWindow) return; XFixesShowCursor(MAIN.dpy, MAIN.CurrentWindow->win);}void la_XErrorHandler(Display *display, XErrorEvent *event){    char buf[512];    XGetErrorText(display, event->error_code, buf, sizeof(buf));    printf("X Error:\n%s\n",buf);}SYSWINDOW la_CreateWindowX11(int x, int y, int w, int h, char *title, int SyncToVBlank, GLXContext* r_glc, void* egl_surf){    XSetWindowAttributes swa;    XWindowAttributes wa;    swa.event_mask =         KeyPressMask|KeyReleaseMask|StructureNotifyMask|SubstructureNotifyMask|        ButtonMotionMask|ButtonPressMask|ButtonReleaseMask|ExposureMask|PointerMotionMask;    swa.colormap = MAIN.cmap;    SYSWINDOW root = DefaultRootWindow(MAIN.dpy);    SYSWINDOW win = XCreateWindow(MAIN.dpy, root, x,y, w, h, 0, MAIN.xvi->depth, InputOutput, MAIN.xvi->visual, CWColormap | CWEventMask, &swa);    XSetWMProtocols(MAIN.dpy , win, &MAIN.MsgDelWindow, 1);    if(x>0||y>0){        XSizeHints    my_hints = {0};        my_hints.flags = PPosition;        my_hints.x = x; my_hints.y = y;        XSetNormalHints(MAIN.dpy, win, &my_hints);    }    XStoreName(MAIN.dpy, win, title);#ifdef LA_USE_GLES    static const EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };    (*r_glc)=eglCreateContext(MAIN.egl_dpy, MAIN.BestFBC, MAIN.glc, ctx_attribs );    if (!(*r_glc)){ printf("\n\tcannot create gl context\n\n"); exit(0); }    EGLSurface* surf=egl_surf;    (*surf)=eglCreateWindowSurface(MAIN.egl_dpy, MAIN.BestFBC, win, NULL);    if (!(*surf)) { printf("Error: eglCreateWindowSurface failed %d\n",eglGetError()); exit(1); }    tnsContextMakeCurrent((*r_glc),win,(*surf));#else    int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, MAIN.GLMajor, GLX_CONTEXT_MINOR_VERSION_ARB, MAIN.GLMinor, 0};    if (((*r_glc) = glXCreateContextAttribsF(MAIN.dpy, MAIN.BestFBC, MAIN.glc, GL_TRUE, attribs)) == NULL){        printf("\n\tcannot create gl context\n\n"); exit(0);    }    tnsContextMakeCurrent((*r_glc),win,0);    int sync=SyncToVBlank?1:0; glXSwapIntervalEXTF(MAIN.dpy, win, sync);#endif    XSetLocaleModifiers("");    MAIN.im = XOpenIM(MAIN.dpy, NULL, NULL, NULL);    if(!MAIN.im){        XSetLocaleModifiers("@im=local");        MAIN.im = XOpenIM(MAIN.dpy, NULL, NULL, NULL);    }    if(!MAIN.im){        XSetLocaleModifiers("@im=none");        MAIN.im = XOpenIM(MAIN.dpy, NULL, NULL, NULL);    }    if(!MAIN.im){        XSetLocaleModifiers("@im=");        MAIN.im = XOpenIM(MAIN.dpy, NULL, NULL, NULL);    }    if(!MAIN.im){        logPrint("Can't open a input method.\n");    }    if(MAIN.im){        MAIN.ic = XCreateIC(MAIN.im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, NULL);        XSetICFocus(MAIN.ic);    }    XClassHint ch; ch.res_name = "LAGUI_WINDOW"; ch.res_class = "LAGUI_WINDOW";    XSetClassHint(MAIN.dpy, win, &ch);#define _NET_WM_STATE_ADD 1    if(w<0&&h<0){        XEvent xev;        Atom wm_state  =  XInternAtom(MAIN.dpy, "_NET_WM_STATE", False);        Atom max_horz  =  XInternAtom(MAIN.dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", False);        Atom max_vert  =  XInternAtom(MAIN.dpy, "_NET_WM_STATE_MAXIMIZED_VERT", False);        memset(&xev, 0, sizeof(xev));        xev.type = ClientMessage;        xev.xclient.window = win;        xev.xclient.message_type = wm_state;        xev.xclient.format = 32;        xev.xclient.data.l[0] = _NET_WM_STATE_ADD;        xev.xclient.data.l[1] = max_horz;        xev.xclient.data.l[2] = max_vert;        XSendEvent(MAIN.dpy, DefaultRootWindow(MAIN.dpy), False, SubstructureNotifyMask, &xev);    }    return win;};void la_DestroySystemWindowX11(laWindow* w) {    tnsContextMakeCurrent(0,0,0);    tnsDeleteContext(w->glc);#ifdef LA_USE_GLES    eglDestroySurface(MAIN.egl_dpy, w->egl_surf);#endif    XDestroyWindow(MAIN.dpy, w->win);};#endif //linux#ifdef _WIN32#include <msgdef.h>#include <wintab.h>#include <wintab_utils.h>#define PACKETDATA	(PK_X | PK_Y | PK_STATUS | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_TIME | PK_CURSOR)#define PACKETMODE	PK_BUTTONS#include <pktdef.h>void la_OpenWacomWinTab(HWND hwnd){    if((!MAIN.WinTabAvailable)||(MAIN.WinTabOpened)) return;    static LOGCONTEXT glogContext = { 0 };    HCTX hctx = NULL;	UINT wDevice = 0; UINT wExtX = 0; UINT wExtY = 0;	UINT wWTInfoRetVal = 0; AXIS TabletX = { 0 }; AXIS TabletY = { 0 };	glogContext.lcOptions |= CXO_SYSTEM;	wWTInfoRetVal = gpWTInfoA(WTI_DEFSYSCTX, 0, &glogContext);	assert(wWTInfoRetVal == sizeof(LOGCONTEXT));	assert(glogContext.lcOptions & CXO_SYSTEM);	wsprintf(glogContext.lcName, "PrsTest Digitizing %p", MAIN.hinstance);	glogContext.lcOptions |= CXO_MESSAGES|CXO_CSRMESSAGES;	glogContext.lcPktData = PACKETDATA;	glogContext.lcPktMode = PACKETMODE;	glogContext.lcMoveMask = PACKETDATA;	glogContext.lcBtnUpMask = glogContext.lcBtnDnMask;	wWTInfoRetVal = gpWTInfoA(WTI_DEVICES + 0, DVC_X, &TabletX);	assert(wWTInfoRetVal == sizeof(AXIS));	wWTInfoRetVal = gpWTInfoA(WTI_DEVICES, DVC_Y, &TabletY);	assert(wWTInfoRetVal == sizeof(AXIS));    AXIS tabletPressure = { 0 };    gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &tabletPressure); MAIN.WinTabMaxPenPressure = tabletPressure.axMax + 1;    //glogContext.lcInOrgX = 0;	//glogContext.lcInOrgY = 0;	//glogContext.lcInExtX = TabletX.axMax;	//glogContext.lcInExtY = TabletY.axMax;    gpWTInfoA(WTI_DEFSYSCTX, CTX_INORGX, &glogContext.lcInOrgX);    gpWTInfoA(WTI_DEFSYSCTX, CTX_INORGY, &glogContext.lcInOrgY);    gpWTInfoA(WTI_DEFSYSCTX, CTX_INEXTX, &glogContext.lcInExtX);    gpWTInfoA(WTI_DEFSYSCTX, CTX_INEXTY, &glogContext.lcInExtY);    gpWTInfoA(WTI_DEFSYSCTX, CTX_OUTORGX, &glogContext.lcOutOrgX);    gpWTInfoA(WTI_DEFSYSCTX, CTX_OUTORGY, &glogContext.lcOutOrgY);    gpWTInfoA(WTI_DEFSYSCTX, CTX_OUTEXTX, &glogContext.lcOutExtX);    gpWTInfoA(WTI_DEFSYSCTX, CTX_OUTEXTY, &glogContext.lcOutExtY);    gpWTInfoA(WTI_DEFSYSCTX, CTX_SYSORGX, &glogContext.lcSysOrgX);    gpWTInfoA(WTI_DEFSYSCTX, CTX_SYSORGY, &glogContext.lcSysOrgY);    gpWTInfoA(WTI_DEFSYSCTX, CTX_SYSEXTX, &glogContext.lcSysExtX);    gpWTInfoA(WTI_DEFSYSCTX, CTX_SYSEXTY, &glogContext.lcSysExtY);    //printf("%d %d\n", glogContext.lcInOrgX, glogContext.lcInOrgY);    //printf("%d %d\n", glogContext.lcInExtX, glogContext.lcInExtY);    //printf("%d %d\n", glogContext.lcOutOrgX, glogContext.lcOutOrgY);    //printf("%d %d\n", glogContext.lcOutExtX, glogContext.lcOutExtY);    //printf("%d %d\n", glogContext.lcSysOrgX, glogContext.lcSysOrgY);    //printf("%d %d\n", glogContext.lcSysExtX, glogContext.lcSysExtY);    glogContext.lcOutOrgX = GetSystemMetrics(SM_XVIRTUALSCREEN);	glogContext.lcOutOrgY = GetSystemMetrics(SM_YVIRTUALSCREEN);	glogContext.lcOutExtX = GetSystemMetrics(SM_CXVIRTUALSCREEN); //SM_CXSCREEN);	glogContext.lcOutExtY = -GetSystemMetrics(SM_CYVIRTUALSCREEN);	// lower left to upper left. SM_CYSCREEN);    //printf("%d %d\n", glogContext.lcOutOrgX, glogContext.lcOutOrgY);    //printf("%d %d\n", glogContext.lcOutExtX, glogContext.lcOutExtY);	hctx = gpWTOpenA(hwnd, &glogContext, FALSE);    if (!hctx)return;    gpWTEnable(hctx, 1); MAIN.WinTabOpened = 1;    logPrintNew("Successfully opened Wacom input device via WinTab.\n");}void laHideCursor() {    if (!MAIN.CurrentWindow) return; //impl}void laShowCursor() {    if (!MAIN.CurrentWindow) return; //impl}static PIXELFORMATDESCRIPTOR cpfd = {    sizeof(PIXELFORMATDESCRIPTOR),1,    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_SWAP_COPY | PFD_DOUBLEBUFFER,    PFD_TYPE_RGBA,    8,    0, 0, 0, 0, 0, 0,    0, 0, 0,    0, 0, 0, 0,    32,    8, 0,    0,    0, 0, 0, 0};void la_SetupPxlFormat(HDC hdc, int* nRegularFormat, int* nMSFormat) {    int nBestMS = 0;    int i;    int iResults[9];    int iAttributes[9] = { WGL_SUPPORT_OPENGL_ARB, // 0        WGL_ACCELERATION_ARB,   // 1        WGL_DRAW_TO_WINDOW_ARB, // 2        WGL_DOUBLE_BUFFER_ARB,  // 3        WGL_PIXEL_TYPE_ARB,     // 4        WGL_DEPTH_BITS_ARB,     // 5        WGL_STENCIL_BITS_ARB,   // 6        WGL_SAMPLE_BUFFERS_ARB, // 7        WGL_SAMPLES_ARB };      // 8    // How many pixelformats are there?    int nFormatCount[] = { 0 };    int attrib[] = { WGL_NUMBER_PIXEL_FORMATS_ARB };    if (!wglGetPixelFormatAttribivARB)        wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)        wglGetProcAddress("wglGetPixelFormatAttribivARB");    wglGetPixelFormatAttribivARB(hdc, 1, 0, 1, attrib, nFormatCount);    for (i = 0; i < nFormatCount[0]; i++){        wglGetPixelFormatAttribivARB(hdc, i + 1, 0, 9, iAttributes, iResults);        if (iResults[0] == 1 && iResults[1] == WGL_FULL_ACCELERATION_ARB && iResults[2] == 1)            if (iResults[3] == 1)                    // Double buffered                if (iResults[4] == WGL_TYPE_RGBA_ARB)    // Full Color                    if (iResults[5] >= 24)                   // Any Depth greater than 16                        if (iResults[6] > 0) { *nRegularFormat = i; break; }    }    SetPixelFormat(hdc, *nRegularFormat, &cpfd);};void la_SetupGLEnviornment(laWindow* window, HWND hwnd, int Sync) {    GLint Attrib[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, MAIN.GLMajor,                  WGL_CONTEXT_MINOR_VERSION_ARB, MAIN.GLMinor,        WGL_CONTEXT_PROFILE_MASK_ARB,WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,        //WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE,        0 };    HGLRC hglrc = 0;    HDC hdc = 0;    int a, b;    hdc = GetDC(hwnd);    la_SetupPxlFormat(hdc, &a, &b);    hglrc = wglCreateContextAttribsARB(hdc, MAIN.glc, Attrib);    if (!hglrc) SEND_PANIC_ERROR("Can't Create Opengl Context!\n", );    tnsContextMakeCurrent(hglrc, hdc,0);    //int sync = Sync ? 1 : 0; wglSwapIntervalEXT(sync);    wglSwapIntervalEXT(-1);    window->win = hwnd; window->glc = hglrc; window->hdc = hdc;};SYSWINDOW la_CreateWindowWin32(int x, int y, int w, int h, char* title, int SyncToVBlank, SYSGLCONTEXT* r_glc) {    HINSTANCE* inst = &MAIN.hinstance;    HWND hwnd = CreateWindowW(LA_GUI_WNDCLASS_NAME, title, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,        x, y, w, h, 0, 0, *inst, 0);    if (!hwnd) { int a = GetLastError(); printf("%d", a); return 0; }    if (!MAIN.WinTabOpened) { la_OpenWacomWinTab(hwnd); }    return hwnd;};void la_DestroySystemWindowWin32(laWindow* w) {    tnsContextMakeCurrent(0,0,0);    tnsDeleteContext(w->glc);    ReleaseDC(w->win, w->hdc);    DestroyWindow(w->win);};#endif#ifdef __linux__void la_HandlerSIGSEGV(int sig) {    void *array[30];    size_t sz;    sz = backtrace(array, 30);    fprintf(stdout, "LaGUI recieved error signal %d:\n The program terminated unexpectedly.\n", sig);    backtrace_symbols_fd(array, sz, STDERR_FILENO);    exit(1);}#endifvoid la_glDebugOutput(GLenum source, GLenum type, unsigned int id,    GLenum severity, GLsizei length, const char* message, const void* userParam) {    // ignore non-significant error/warning codes    if (id==131169 || id==131185 || id==131218 || id==131204 || id==131076) return;    logPrint("GL %d: %s\n", id, message);    char* strsource="",*strtype="",*strseverity="";    switch (source) {    case GL_DEBUG_SOURCE_API:             strsource = "API"; break;    case GL_DEBUG_SOURCE_WINDOW_SYSTEM:   strsource = "Window System"; break;    case GL_DEBUG_SOURCE_SHADER_COMPILER: strsource = "Shader Compiler"; break;    case GL_DEBUG_SOURCE_THIRD_PARTY:     strsource = "Third Party"; break;    case GL_DEBUG_SOURCE_APPLICATION:     strsource = "Application"; break;    case GL_DEBUG_SOURCE_OTHER:           strsource = "Other"; break;    }    switch (type) {    case GL_DEBUG_TYPE_ERROR:               strtype = "Error"; break;    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: strtype = "Deprecated Behaviour"; break;    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:  strtype = "Undefined Behaviour"; break;    case GL_DEBUG_TYPE_PORTABILITY:         strtype = "Portability"; break;    case GL_DEBUG_TYPE_PERFORMANCE:         strtype = "Performance"; break;    case GL_DEBUG_TYPE_MARKER:              strtype = "Marker"; break;    case GL_DEBUG_TYPE_PUSH_GROUP:          strtype = "Push Group"; break;    case GL_DEBUG_TYPE_POP_GROUP:           strtype = "Pop Group"; break;    case GL_DEBUG_TYPE_OTHER:               strtype = "Other"; break;    }    switch (severity) {    case GL_DEBUG_SEVERITY_HIGH:         strseverity = "High"; break;    case GL_DEBUG_SEVERITY_MEDIUM:       strseverity = "Medium"; break;    case GL_DEBUG_SEVERITY_LOW:          strseverity = "Low"; break;    case GL_DEBUG_SEVERITY_NOTIFICATION: strseverity = "Notification"; break;    }    logPrint("%s | %s | %s\n\n", strsource,strtype,strseverity);}void la_SetCurrentGLContextDebug(){    int force=MAIN.InitArgs.GLDebug;    if(MAIN.EnableGLDebug || force){ glEnable(GL_DEBUG_OUTPUT); }else{ glDisable(GL_DEBUG_OUTPUT); }    if(MAIN.GLDebugSync || force){ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); }else{ glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS); }    glDebugMessageCallback(la_glDebugOutput, 0);    int sev=GL_DONT_CARE;    if(!force){        switch(MAIN.GLDebugLevel){         default: sev=GL_DONT_CARE; break;        case 1: sev=GL_DEBUG_SEVERITY_NOTIFICATION; break;        case 2: sev=GL_DEBUG_SEVERITY_LOW; break;        case 3: sev=GL_DEBUG_SEVERITY_MEDIUM; break;        case 4: sev=GL_DEBUG_SEVERITY_HIGH; break;        }    }    glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, sev, 0, 0, GL_TRUE);}void la_NotifyGLDebugChanges(){    MAIN.GLDebugNeedsUpdate=1; for(laWindow* w=MAIN.Windows.pFirst;w;w=w->Item.pNext){ w->GLDebugNeedsUpdate=1; }}void la_SetupWindowGLStates(laWindow* w){    tnsBindVertexArray(w->vao); tnsUnbindTexture(); tnsUseImmShader(); tnsEnableShaderv(T->immShader);    if(w->GLDebugNeedsUpdate){        tnsContextMakeWindowCurrent(w);        la_SetCurrentGLContextDebug(); w->GLDebugNeedsUpdate=0;    }}int la_CreateSystemWindow(laWindow *window, int SyncToVBlank){    SYSGLCONTEXT glc;#ifdef __linux__    void* egl_surf=0;#ifdef LA_USE_GLES    egl_surf=&window->egl_surf;#endif    SYSWINDOW hwnd = la_CreateWindowX11(window->X, window->Y, window->W, window->H, window->Title->Ptr, SyncToVBlank, &glc, egl_surf);#endif#ifdef _WIN32    SYSWINDOW hwnd = la_CreateWindowWin32(window->X, window->Y, window->W, window->H, window->Title->Ptr, SyncToVBlank, &glc);#endif    window->win = hwnd;    window->glc = glc;#ifdef _WIN32    la_SetupGLEnviornment(window, hwnd, SyncToVBlank);    RECT rc; GetClientRect(window->win, &rc);    window->CW = rc.right - rc.left;    window->CH = rc.bottom - rc.top;#endif#ifdef __linux__    XWindowAttributes attr;    XGetWindowAttributes(MAIN.dpy, window->win, &attr);    window->CW =attr.width;    window->CH = attr.height;#endif    la_SetCurrentGLContextDebug();    glGenVertexArrays(1,&window->vao); tnsBindVertexArray(window->vao);    la_SetupWindowGLStates(window);#ifdef LA_USE_GLES    window->nvg=nvgCreateGLES3(NVG_STENCIL_STROKES|NVG_DEBUG|NVG_ANTIALIAS);#else    window->nvg=nvgCreateGL3(NVG_STENCIL_STROKES|NVG_DEBUG|NVG_ANTIALIAS);#endif    window->OutputShowStripes=1; window->Redraw=1;    window->GLDebugNeedsUpdate=1;    window->UseComposing=0; window->ComposingGamma=1.0; window->ComposingBlackpoint=0.0;    return 1;};int la_DestroySystemWindow(laWindow* wnd){#ifdef LA_USE_GLES    nvgDeleteGLES3(wnd->nvg);#else    nvgDeleteGL3(wnd->nvg);#endif#ifdef __linux__    la_DestroySystemWindowX11(wnd);#endif#ifdef _WIN32    la_DestroySystemWindowWin32(wnd);#endif}void la_DestroyWindow(laWindow *wnd){    laLayout *l; laPanel *p; if (!wnd) return;        tnsSwitchToCurrentWindowContext(wnd);    tnsBindVertexArray(0); glDeleteVertexArrays(1,&wnd->vao);    la_StopAllOperators();    strSafeDestroy(&wnd->Title);    //la_PrintUserList(wnd);    //printf("----\n");    while (p = lstPopItem(&wnd->Panels)){ laDestroySinglePanel(p,1); }    while (l = lstPopItem(&wnd->Layouts)){        laDestroyBlocksRecursive(l->FirstBlock);        //la_PrintUserList(l);        //printf("%x %s\n", l, l->ID->Ptr);        strSafeDestroy(&l->ID);        memFree(l);        //la_PrintUserList(wnd);        //printf("----\n");    }    //printf("----\n%x\n",wnd);    //la_PrintUserList(wnd);    la_DestroySystemWindow(wnd);    lstRemoveItem(&MAIN.Windows, wnd);    memFree(wnd);    MAIN.CurrentWindow=MAIN.Windows.pFirst;}void laRenameWindow(laWindow* wnd, char* name){    if((!wnd)||MAIN.IsReadingUDF) return;    strSafeSet(&wnd->Title, name);    if(!wnd->win) return;#ifdef __linux__    XStoreName(MAIN.dpy, wnd->win, name);#endif#ifdef _WIN32    //wchar_t buf[128]; MultiByteToWideChar(CP_UTF8, 0, name, -1, buf, 128);    SetWindowTextW(wnd->win, name);#endif}#ifdef __linux__const char* la_ConvertCursorID(int id){    switch (id) {    case LA_ARROW: return "arrow";    case LA_CROSS: return "cross";    case LA_LEFT_AND_RIGHT: return "sb_h_double_arrow";    case LA_UP_AND_DOWN: return "sb_v_double_arrow";    case LA_MOVE: return "diamond_cross";    case LA_HAND: return "hand1";    case LA_CORNER: return "bottom_right_corner";    }    return "arrow";}#endif#ifdef _WIN32HCURSOR la_ConvertCursorID(int id){    switch (id){    case LA_ARROW: return LoadCursor(0,IDC_ARROW);    case LA_CROSS: return LoadCursor(0,IDC_CROSS);    case LA_LEFT_AND_RIGHT: return LoadCursor(0,IDC_SIZEWE);    case LA_UP_AND_DOWN: return LoadCursor(0, IDC_SIZENS);    case LA_MOVE: return LoadCursor(0, IDC_SIZEALL);    case LA_HAND: return LoadCursor(0, IDC_HAND);    case LA_CORNER: return LoadCursor(0, IDC_SIZENWSE);    }    return LoadCursor(0, IDC_ARROW);;}#endifvoid la_InitThreadEnviornment(){    //pthread_spin_init(&MAIN.csNotifier, //pthread_PROCESS_PRIVATE);}laLogEntry* logEnsure(int Create){    if(!MAIN.Logs.pFirst || Create){        laLogEntry* le=memAcquireSimple(sizeof(laLogEntry));        lstAppendItem(&MAIN.Logs, le);    }    return MAIN.Logs.pLast;}void logPrintTV(int Continued, char* format, va_list v){    if(!format || !format[0]) return;    laLogEntry* le=logEnsure(Continued);    if(MAIN.EnableLogStdOut){ va_list v1; va_copy(v1,v); vprintf(format,v1); }    strSafePrintV(&le->Content, format, v);    laNotifyUsers("la.logs");}void logPrintT(int Continued, char* format, ...){    if(!format || !format[0]) return;    laLogEntry* le=logEnsure(Continued);    va_list aptr; va_start(aptr, format);    strSafePrint(&le->Content, format, aptr);    va_end(aptr);    laNotifyUsers("la.logs");}void logPrint(char* format, ...){    va_list aptr; va_start(aptr, format);    logPrintTV(0, format, aptr);    va_end(aptr);}void logPrintNew(char* format, ...){    logEnsure(1);    va_list aptr; va_start(aptr, format);    logPrintTV(0, format, aptr);    va_end(aptr);}void logClear(){    laLogEntry*l;    while(l=lstPopItem(&MAIN.Logs)){ strSafeDestroy(&l->Content); memFree(l); }    laNotifyUsers("la.logs");}laScreen* la_EnsureScreen(char* Name, int mmw, int mmh, int x, int y, int w, int h,int dpi){ if(!Name || !Name[0]) return 0;    for(laScreen* s=MAIN.Screens.pFirst;s;s=s->Item.pNext){        if(strSame(SSTR(s->Name),Name)){ s->x=x;s->y=y;s->w=w;s->h=h; return s; }    }    laScreen* s=memAcquire(sizeof(laScreen)); lstAppendItem(&MAIN.Screens,s);    strSafeSet(&s->Name,Name);    strSafePrint(&s->Description,"%dmm x %dmm with %dx%d ~%ddpi",mmw,mmh,w,h,dpi); s->RoughDPI=dpi;    s->x=x;s->y=y;s->w=w;s->h=h;    return s;}void la_RemoveScreen(laScreen*s){    strSafeDestroy(&s->Description); strSafeDestroy(&s->Name);    lstRemoveItem(&MAIN.Screens,s); memFree(s);}void la_RemoveDuplicatedScreenConf(){    laScreen* NextS;    for(laScreen* s=MAIN.Screens.pFirst;s;s=NextS){        NextS = s->Item.pNext;        for(laScreen* fs=s->Item.pNext;fs;fs=fs->Item.pNext){            if(strSame(SSTR(fs->Name),SSTR(s->Name))){ fs->x=s->x;fs->y=s->y;fs->w=s->w;fs->h=s->h; la_RemoveScreen(s); break; }        }    }}laScreen* laGetWindowScreen(laWindow* w){    int l,r,u,b; int area=-1; laScreen* maxs=0;    for(laScreen* s=MAIN.Screens.pFirst;s;s=s->Item.pNext){        l=TNS_MAX2(s->x,w->X); r=TNS_MIN2(s->x+s->w,w->X+w->W);        u=TNS_MAX2(s->y,w->Y); b=TNS_MIN2(s->y+s->h,w->Y+w->H);        int w=(r-l); if(w<0){w=0;} int h=(b-u); if(h<0){h=0;}        int a=w*h; if(a>area){ maxs = s; area = a; }    }    return maxs;}#ifdef __linux__int la_GetDPI(Window* root_win){    XRRScreenResources *screen;    XRROutputInfo *info;    XRRCrtcInfo *crtc_info;    XRRCrtcInfo *crtc;    int iscres, icrtc, dpi=0;    screen=XRRGetScreenResources(MAIN.dpy, root_win);    for(iscres=0;iscres<screen->noutput;iscres++){        info=XRRGetOutputInfo(MAIN.dpy,screen,screen->outputs[iscres]);        if(!info->mm_width || !info->mm_height){ continue; }        logPrint("    Xrandr reported output size: %dmm x %dmm\n",info->mm_width,info->mm_height);        crtc=XRRGetCrtcInfo(MAIN.dpy,screen,info->crtc);        dpi=(real)crtc->width/(real)info->mm_width*25.4;        logPrint("    CRTC: %d x %d, around %ddpi\n",crtc->width,crtc->height,dpi);        laScreen* s=la_EnsureScreen(info->name,info->mm_width,info->mm_height,crtc->x,crtc->y,crtc->width,crtc->height,dpi);        XRRFreeCrtcInfo(crtc);        //if(info->connection==RR_Connected){        //    for (icrtc=0;icrtc<info->ncrtc;icrtc++) {        //        crtc_info=XRRGetCrtcInfo(MAIN.dpy,screen,screen->crtcs[icrtc]);        //        printf("==> %d,%d + %dx%d\n", crtc_info->x, crtc_info->y, crtc_info->width, crtc_info->height);        //        XRRFreeCrtcInfo(crtc_info);        //    }        //}        XRRFreeOutputInfo(info);    }    XRRFreeScreenResources(screen);    return dpi;}#endif#ifdef _WIN32int la_GetDPI(HWND win){    return GetDpiForWindow(win);    return 144;}#endif#define PROGRESSW (LA_RH*15)void laShowProgress(real p1, real p2){    laBoxedTheme *bt = _LA_THEME_TAB; real* fg=laThemeColor(bt,LA_BT_TEXT); real* bg=laThemeColor(bt,LA_BT_NORMAL);    if(!MAIN.Progress.Called){        laRecordTime(&MAIN.Progress.TimeCalled); MAIN.Progress.Called=1;    }else{        laTimeRecorder tm; laRecordTime(&tm);        real t=laTimeElapsedSecondsf(&tm,&MAIN.Progress.TimeCalled); if(t<0.1) return;        memcpy(&MAIN.Progress.TimeCalled,&tm,sizeof(laTimeRecorder));        if(!MAIN.Progress.Shown){             int ww=PROGRESSW+LA_RH*2;#ifdef __linux__            int w=XDisplayWidth(MAIN.dpy, 0),h=XDisplayHeight(MAIN.dpy, 0);            XMoveResizeWindow(MAIN.dpy,MAIN.Progress.w,w/2-ww/2,h/2-LA_RH*2/2,ww,LA_RH*2);            long a=LA_COLOR3_TO_HEX(bg);            XSetForeground(MAIN.dpy,MAIN.Progress.gc,LA_COLOR3_TO_HEX(fg));            XSetBackground(MAIN.dpy,MAIN.Progress.gc,LA_COLOR3_TO_HEX(bg));            XSetWindowBackground(MAIN.dpy,MAIN.Progress.w,LA_COLOR3_TO_HEX(bg));            if(MAIN.CurrentWindow) XSetTransientForHint(MAIN.dpy,MAIN.Progress.w,MAIN.CurrentWindow->win);            XMapWindow(MAIN.dpy,MAIN.Progress.w);#endif#ifdef _WIN32            int w=GetSystemMetrics(SM_CXFULLSCREEN), h=GetSystemMetrics(SM_CYFULLSCREEN);            SetWindowPos(MAIN.Progress.w, MAIN.CurrentWindow->win,w/2-ww/2,h/2-LA_RH*2/2,ww,LA_RH*2,0);            ShowWindow(MAIN.Progress.w,SW_SHOW);#endif            MAIN.Progress.Shown = 1;        }    }    if(p1>=0) MAIN.Progress.p1=p1; if(p2>=0) MAIN.Progress.p2=p2;#ifdef __linux__    XClearWindow(MAIN.dpy,MAIN.Progress.w);    XFillRectangle(MAIN.dpy,MAIN.Progress.w,MAIN.Progress.gc,LA_RH*2,0,PROGRESSW*MAIN.Progress.p1,LA_RH);    XFillRectangle(MAIN.dpy,MAIN.Progress.w,MAIN.Progress.gc,LA_RH*2,LA_RH,PROGRESSW*MAIN.Progress.p2,LA_RH);    tnsDrawLCD7_ProgressSystem(LA_RH*1.5,0,MAIN.Progress.p1);    tnsDrawLCD7_ProgressSystem(LA_RH*1.5,LA_RH,MAIN.Progress.p2);    XSync(MAIN.dpy, 1); XFlush(MAIN.dpy);#endif#ifdef _WIN32    InvalidateRect(MAIN.Progress.w,0,1);    if(!MAIN.Progress.brush_bg){ MAIN.Progress.brush_bg=CreateSolidBrush(LA_COLOR3_TO_RGB(bg)); }    if(!MAIN.Progress.brush_fg){ MAIN.Progress.brush_fg=CreateSolidBrush(LA_COLOR3_TO_RGB(fg)); }    if(!MAIN.Progress.pen_fg){ MAIN.Progress.pen_fg=CreatePen(PS_SOLID, 2, LA_COLOR3_TO_RGB(fg)); }    RECT rect; GetClientRect(MAIN.Progress.w, &rect);    PAINTSTRUCT ps; BeginPaint(MAIN.Progress.w,&ps);    SelectObject(MAIN.Progress.hdc, MAIN.Progress.brush_bg);    Rectangle(MAIN.Progress.hdc, 0, 0, rect.right, rect.bottom);    SelectObject(MAIN.Progress.hdc, MAIN.Progress.brush_fg);    Rectangle(MAIN.Progress.hdc,LA_RH*2,0,LA_RH*2+PROGRESSW*MAIN.Progress.p1,LA_RH);    Rectangle(MAIN.Progress.hdc,LA_RH*2,LA_RH,LA_RH*2+PROGRESSW*MAIN.Progress.p2,LA_RH+LA_RH);    SelectObject(MAIN.Progress.hdc, MAIN.Progress.pen_fg);    tnsDrawLCD7_ProgressSystem(LA_RH*1.5,0,MAIN.Progress.p1);    tnsDrawLCD7_ProgressSystem(LA_RH*1.5,LA_RH,MAIN.Progress.p2);    EndPaint(MAIN.Progress.w,&ps);    MSG msg;    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){ TranslateMessage(&msg); DispatchMessage(&msg); };#endif}void laHideProgress(){    if(!MAIN.Progress.Shown){        MAIN.Progress.Called=0; return;    }    laTimeRecorder tm; laRecordTime(&tm);    real t=laTimeElapsedSecondsf(&tm,&MAIN.Progress.TimeCalled);    if(t<0.2){ usleep((TNS_MIN2(0.2-t,0.2))*1000000); }    MAIN.Progress.Called = MAIN.Progress.Shown = 0;#ifdef __linux__    XUnmapWindow(MAIN.dpy,MAIN.Progress.w); XSync(MAIN.dpy, 1); XFlush(MAIN.dpy);#endif#ifdef _WIN32    ShowWindow(MAIN.Progress.w,SW_HIDE);    if(MAIN.CurrentWindow) UpdateWindow(MAIN.CurrentWindow->win);#endif}//=======================void la_InitProgressWindow(){#ifdef __linux__    MAIN.Progress.w=XCreateSimpleWindow(MAIN.dpy, RootWindow(MAIN.dpy, 0), 0, 0, PROGRESSW+LA_RH*2, LA_RH*2, 0, BlackPixel(MAIN.dpy, 0), WhitePixel(MAIN.dpy, 0));    if(!MAIN.Progress.w) return;    Atom window_type = XInternAtom(MAIN.dpy, "_NET_WM_WINDOW_TYPE", False); long value = XInternAtom(MAIN.dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);    XChangeProperty(MAIN.dpy, MAIN.Progress.w, window_type,XA_ATOM, 32, PropModeReplace, (unsigned char *) &value,1 );    MAIN.Progress.gc=XCreateGC(MAIN.dpy,MAIN.Progress.w,0,&MAIN.Progress.gc_values);    if(MAIN.Progress.gc<0) return;    XSetFillStyle(MAIN.dpy, MAIN.Progress.gc, FillSolid);    XSetLineAttributes(MAIN.dpy, MAIN.Progress.gc, 2, LineSolid, CapButt, JoinBevel);    XSync(MAIN.dpy,0);#endif#ifdef _WIN32    WNDCLASSW wc;    wc.hInstance = MAIN.hinstance;    wc.lpfnWndProc = LA_ProgressWindowProc;    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);    wc.hCursor = LoadCursor(NULL, IDC_ARROW);    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    wc.cbWndExtra = 0;    wc.cbClsExtra = 0;    wc.lpszClassName = L"_LAGUIPROGRESS";    wc.lpszMenuName = NULL;    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;    if (!RegisterClassW(&wc)){ return; }        MAIN.Progress.w=CreateWindowW(L"_LAGUIPROGRESS",L"Progress", WS_POPUP, 0,0,PROGRESSW+LA_RH*2,LA_RH*2,0,0,MAIN.hinstance,0);    MAIN.Progress.hdc=GetDC(MAIN.Progress.w);#endif}void laSetFontFolderPath(char* absolute){    strcpy(MAIN.SysFontDir,absolute); int len=strlen(MAIN.SysFontDir);    if(MAIN.SysFontDir[len-1]!='/'){ MAIN.SysFontDir[len]='/'; MAIN.SysFontDir[len+1]=0; }}void laSetDefaultInitArguments(laInitArguments* ia){    ia->GLMajor=3; ia->GLMinor=3; ia->BufferSamples=0;    ia->UseColorManagement=0;    ia->HasWorldObjects=0;    ia->HasAction=0;    ia->HasTextureInspector=0;    ia->HasHistories=0;    ia->HasTerminal=1;    ia->HasAudio=0;}void laSetCompleteInitArguments(laInitArguments* ia){    ia->GLMajor=3; ia->GLMinor=3; ia->BufferSamples=0;    ia->UseColorManagement=1;    ia->HasWorldObjects=1;    ia->HasAction=1;    ia->HasTextureInspector=1;    ia->HasHistories=1;    ia->HasTerminal=1;    ia->HasAudio=1;}void laProcessInitArguments(int argc, char* argv[],laInitArguments* ia) {    MAIN.GLMajor=MAIN.GLMinor=-1;    char* arg = 0;    printf("Initializing LaGUI...\n",argc);    for(int i=0;i<argc;i++){        if(strstr(argv[i], "--gl-version=")==argv[i]){ arg=&argv[i][strlen(argv[i])-3];            if(arg[0]>='2'&&arg[0]<='4'&&arg[1]=='.'&&arg[2]>='0'&&arg[2]<='9'){                ia->GLMajor=arg[0]-'0'; ia->GLMinor=arg[2]-'0';                printf("Set gl-version = %d.%d\n",ia->GLMajor,ia->GLMinor);            }            continue;        }        if(strSame(argv[i], "--gl-debug")){ ia->GLDebug=1; printf("Enabled OpenGL Debug.\n"); }        if(strSame(argv[i], "--log")){ ia->EnableLogStdOut=1; printf("Enabled log output to stdout.\n"); }    }}int laGetReadyWith(laInitArguments* ia){#ifdef __linux__    //signal(SIGSEGV,la_HandlerSIGSEGV);#endif    laSpinInit(&MAIN.MemLock);    memcpy(&MAIN.InitArgs,ia,sizeof(laInitArguments));    if(MAIN.InitArgs.GLMajor>4||MAIN.InitArgs.GLMajor<1){ MAIN.InitArgs.GLMajor=3; }    if(MAIN.InitArgs.GLMinor<1){ MAIN.InitArgs.GLMinor=3; }    if(MAIN.BufferSamples==1){ MAIN.BufferSamples=0; }    tnsInit();#ifdef __linux__    SYSWINDOW root, win;    GLint att[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None};    XSetWindowAttributes swa={0};    XWindowAttributes wa={0};    XEvent xev;    logPrintNew("Initializing LaGUI...\n");    setlocale(LC_CTYPE, "zh_CN.utf8");    XSetErrorHandler(la_XErrorHandler);    int i;    if ((MAIN.dpy = XOpenDisplay(NULL)) == NULL){        printf("\n\tcannot connect to x server\n\n");        exit(0);    }    la_ScanWacomDevices(MAIN.dpy,XIAllDevices);        MAIN.GLMajor=MAIN.InitArgs.GLMajor; MAIN.GLMinor=MAIN.InitArgs.GLMinor; MAIN.BufferSamples=MAIN.InitArgs.BufferSamples;    logPrint("Chosen OpenGL version %d.%d\n",MAIN.GLMajor,MAIN.GLMinor);#ifdef LA_USE_GLES    MAIN.egl_dpy=eglGetDisplay(MAIN.dpy);    if(!MAIN.egl_dpy){ printf("Error: eglGetDisplay() failed\n"); exit(1); }    EGLint egl_major, egl_minor;    if (!eglInitialize(MAIN.egl_dpy, &egl_major, &egl_minor)) {        printf("Error: eglInitialize() failed\n"); return -1;    }    int scrnum;    XSetWindowAttributes attr;    XVisualInfo *visInfo, visTemplate;    int num_visuals;    EGLContext ctx;    EGLint num_configs;    EGLint vid;    static const EGLint attribs[] = {        EGL_RED_SIZE, 8,        EGL_GREEN_SIZE, 8,        EGL_BLUE_SIZE, 8,        EGL_DEPTH_SIZE, 1,        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,        EGL_NONE    };    if (!eglChooseConfig(MAIN.egl_dpy, attribs, &MAIN.BestFBC, 1, &num_configs)) {        printf("Error: couldn't get an EGL visual config\n"); exit(1);    }    if (!eglGetConfigAttrib(MAIN.egl_dpy, MAIN.BestFBC, EGL_NATIVE_VISUAL_ID, &vid)) {        printf("Error: eglGetConfigAttrib() failed\n"); exit(1);    }    visTemplate.visualid = vid;    visInfo = XGetVisualInfo(MAIN.dpy, VisualIDMask, &visTemplate, &num_visuals);    if (!visInfo) {        printf("Error: couldn't get X visual\n"); exit(1);    }    MAIN.xvi=visInfo;    root = DefaultRootWindow(MAIN.dpy);    if ((MAIN.cmap = XCreateColormap(MAIN.dpy, root, MAIN.xvi->visual, AllocNone)) == 0){        printf("\n\tcannot create colormap\n\n"); exit(1);    }    eglBindAPI(EGL_OPENGL_ES_API);    static const EGLint ctx_attribs[] = {        EGL_CONTEXT_CLIENT_VERSION, 2,        EGL_NONE    };    MAIN.glc = eglCreateContext(MAIN.egl_dpy, MAIN.BestFBC, EGL_NO_CONTEXT, ctx_attribs);    if (!MAIN.glc) {        printf("Error: eglCreateContext failed\n"); exit(1);    }    eglMakeCurrent(MAIN.egl_dpy,EGL_NO_SURFACE,EGL_NO_SURFACE,MAIN.glc);#else    int visual_attribs[] = {        GLX_X_RENDERABLE    , True,        GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,        GLX_RENDER_TYPE     , GLX_RGBA_BIT,        GLX_X_VISUAL_TYPE   , GLX_TRUE_COLOR,        GLX_RED_SIZE        , 8,        GLX_GREEN_SIZE      , 8,        GLX_BLUE_SIZE       , 8,        GLX_ALPHA_SIZE      , 8,        GLX_DEPTH_SIZE      , 24,        //GLX_STENCIL_SIZE    , 8,        GLX_DOUBLEBUFFER    , True,        GLX_SAMPLE_BUFFERS  , MAIN.BufferSamples?1:0,        GLX_SAMPLES         , MAIN.BufferSamples?MAIN.BufferSamples:0,        None    };    int fbcount = -1;    GLXFBConfig* fbconfig = glXChooseFBConfig(MAIN.dpy, DefaultScreen(MAIN.dpy), visual_attribs, &fbcount );    logPrint("glXChooseFBConfig matched %d\n",fbcount);    if (!fbcount){ printf("\n\tno matching visual\n\n"); exit(0); }    MAIN.BestFBC = fbconfig[0];    int sample_buf,samples;    glXGetFBConfigAttrib(MAIN.dpy, MAIN.BestFBC, GLX_SAMPLE_BUFFERS, &sample_buf);    glXGetFBConfigAttrib(MAIN.dpy, MAIN.BestFBC, GLX_SAMPLES, &samples);    logPrint("    Chosen framebuffer with: %s %d samples\n",sample_buf?"Multisample":"-",samples);    MAIN.xvi=glXGetVisualFromFBConfig(MAIN.dpy, MAIN.BestFBC);    free(fbconfig);    root = DefaultRootWindow(MAIN.dpy);    if ((MAIN.cmap = XCreateColormap(MAIN.dpy, root, MAIN.xvi->visual, AllocNone)) == 0){        printf("\n\tcannot create colormap\n\n"); exit(0);    }    swa.colormap = MAIN.cmap;    root = DefaultRootWindow(MAIN.dpy);    win = XCreateWindow(MAIN.dpy, root, 0, 0, 100, 100, 0, MAIN.xvi->depth, InputOutput, MAIN.xvi->visual, CWBackPixel | CWBorderPixel|CWColormap | CWEventMask, &swa);    MAIN.win=win;    int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, MAIN.GLMajor, GLX_CONTEXT_MINOR_VERSION_ARB, MAIN.GLMinor, 0};    glXCreateContextAttribsF = (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );    if ((MAIN.glc = glXCreateContextAttribsF(MAIN.dpy, MAIN.BestFBC, NULL, GL_TRUE, attribs)) == NULL){        printf("\n\tcannot create gl context\n\n"); exit(0);    }    glXSwapIntervalEXTF = (glXSwapIntervalEXTProc) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalEXT" );    tnsContextMakeCurrent(MAIN.glc,win,0);    int major,minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor);    logPrint("    OpenGL Version: %d.%d\n",major,minor);    logPrint("    OpenGL Renderer: %s\n",glGetString(GL_RENDERER));    int err=0;    if((err=glewInit())!=GLEW_OK){        printf("%d\n",err); printf("%s\n",glewGetErrorString(err));    };#endif /* gles or glx */    glGenVertexArrays(1,&MAIN.TempVAO); tnsBindVertexArray(MAIN.TempVAO);    la_SetCurrentGLContextDebug();    MAIN.MsgDelWindow = XInternAtom(MAIN.dpy, "WM_DELETE_WINDOW", 0);    MAIN.bufid =  XInternAtom(MAIN.dpy, "CLIPBOARD", False),    MAIN.fmtid =  XInternAtom(MAIN.dpy, "UTF8_STRING", False),    MAIN.propid = XInternAtom(MAIN.dpy, "XSEL_DATA", False),    MAIN.incrid = XInternAtom(MAIN.dpy, "INCR", False);    MAIN.targets_atom = XInternAtom(MAIN.dpy, "TARGETS",0);    MAIN.text_atom =    XInternAtom(MAIN.dpy, "TEXT", 0);    MAIN.UTF8 =         XInternAtom(MAIN.dpy, "UTF8_STRING", 1);    MAIN.selection =    XInternAtom(MAIN.dpy, "CLIPBOARD", 0);	if(MAIN.UTF8 == None) MAIN.UTF8 = XA_STRING;    MAIN.wmstate=XInternAtom(MAIN.dpy,"_NET_WM_STATE",1);    MAIN.wmfullscr=XInternAtom(MAIN.dpy,"_NET_WM_STATE_FULLSCREEN",0);    MAIN.wmfullscroff=XInternAtom(MAIN.dpy,"_NET_WM_STATE_FULLSCREEN",0);#endif //linux#ifdef _WIN32    logPrintNew("Initializing LaGUI...\n");    SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);    setlocale(LC_ALL, "zh_CN.utf8");    MAIN.hinstance = GetModuleHandle(NULL);    HINSTANCE* hInst = &MAIN.hinstance;    WNDCLASSEXW wt;    wt.cbSize = sizeof(WNDCLASSEXW);    wt.cbClsExtra = 0;    wt.cbWndExtra = 0;    wt.hbrBackground = 0;    wt.hCursor = LoadCursor(0, IDC_ARROW);    wt.hIcon = LoadIcon(*hInst, IDI_WINLOGO);    wt.hIconSm = LoadIcon(*hInst, IDI_WINLOGO);    wt.hInstance = *hInst;    wt.lpfnWndProc = LA_WindowProc;    wt.lpszClassName = LA_GUI_WNDCLASS_NAME;    wt.lpszMenuName = 0;    wt.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;    if (!RegisterClassExW(&wt)) return 0;        MAIN.GLMajor=MAIN.InitArgs.GLMajor; MAIN.GLMinor=MAIN.InitArgs.GLMinor; MAIN.BufferSamples=MAIN.InitArgs.BufferSamples;    logPrint("Chosen OpenGL version %d.%d\n", MAIN.GLMajor, MAIN.GLMinor);    SetProcessDPIAware();    GLenum err;    PIXELFORMATDESCRIPTOR pfd;    HINSTANCE* hinst = &MAIN.hinstance;    HWND hwnd = CreateWindowExW(WS_EX_ACCEPTFILES, LA_GUI_WNDCLASS_NAME,        "Temp Window For Accessing GLEW!",        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 100, 100,        0, 0, *hinst, 0);    HDC hdc = GetDC(hwnd);    HGLRC hglrc = 0;    SetPixelFormat(hdc, 1, &cpfd);    hglrc = wglCreateContext(hdc);    tnsContextMakeCurrent(hglrc, hdc,0);    //MAIN.hdc = hdc;   // MAIN.tWND = hwnd;    MAIN.glc = hglrc;    int major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor);    logPrint("    OpenGL Version: %d.%d\n", major, minor);    logPrint("    OpenGL Renderer: %s\n", glGetString(GL_RENDERER));    if (err = glewInit()) {        printf("Init Glew Failed\n");        printf("glewGetErrorString: %s\n", glewGetErrorString(err));        return 0;    }    logPrint("Trying to load WinTab for stylus input...\n"); int WtAvailable=1;    if (!LoadWintab()){ logPrint("WinTab not available.\n"); WtAvailable=0; }	elif (!gpWTInfoA(0, 0, NULL)){ logPrint("WinTab service is not available. (gpWTInfoA() returns 0).\n"); WtAvailable=0; }    if (WtAvailable){ MAIN.WinTabAvailable=1; logPrint("WinTab service is available.\n"); }#endif    la_GetWorkingDirectoryInternal();    MAIN.SavePreferenceOnExit=1;        MAIN.FontSize = 0.6;#ifdef _WIN32    int dpi=la_GetDPI(hwnd);#endif#ifdef __linux__    int dpi = la_GetDPI(DefaultRootWindow(MAIN.dpy));#endif    if((!dpi) || dpi<144){ dpi=144; } if(dpi>300){ dpi=300; }    int UiSize=(int)(tnsLinearItp(16.0f,24.0f,tnsGetRatiod(96,144,dpi))+0.5);        MAIN.UiRowHeight = MAIN.ScaledUiRowHeight =UiSize;    MAIN.UiScale=1;    MAIN.MarginSize = 1;    MAIN.ColorPickerGamma=1.5;    MAIN.EnableColorManagement=MAIN.InitArgs.UseColorManagement;    MAIN.ViewportHalftoneFactor=0.5;    MAIN.ViewportHalftoneSize=3.7;    tnsInitRenderKernel(64);    tnsInitBuiltinShaders();    tnsSetuptnsFontManager();#define LOAD_FONT(font) \    if(!tnsLoadSystemFont(MAIN.SysFontDir, font)) printf("Can't load font \"" font "\"\n");    LOAD_FONT("NotoSansCJK-Regular.ttc");    LOAD_FONT("NotoEmoji-Regular.ttf");    LOAD_FONT("NotoSansSymbols-Regular.ttf");    LOAD_FONT("NotoSansSymbols2-Regular.ttf");    //LOAD_FONT("NotoMusic-Regular.ttf");    //LOAD_FONT("NotoSansEgyptianHieroglyphs-Regular.ttf);    if(!tnsLoadSystemFontMono(MAIN.SysFontDir, "NotoSansMono-Regular.ttf")) printf("Can't load font \"NotoSansMono-Regular.ttf\"\n");;    arrEnsureLength(&MAIN.InputBuf,0,&MAIN.InputBufMax,sizeof(char));    arrEnsureLength(&MAIN.InputBufU,0,&MAIN.InputBufUMax,sizeof(uint32_t));    arrEnsureLength(&MAIN.NodeTypes,0,&MAIN.NodeTypeMax,sizeof(laBaseNode*));        MAIN.InputMapping=memAcquire(sizeof(laInputMappingBundle));    MAIN.Animation=memAcquire(sizeof(laAnimation));    MAIN.Audio=memAcquire(sizeof(laAudio));#ifdef LA_WITH_LUAJIT    // starting lua    logPrint("Starting luajit...\n");    MAIN.L = lua_open();    la_luaLoadLibs(MAIN.L);    la_luaPrintStatus(MAIN.L);    tnsLuaInit(MAIN.L);#endif        //interactions:    MAIN.TopFramerate = 60;    MAIN.ValuatorThreshold = 8;    MAIN.ScrollingSpeed = 3;    MAIN.AnimationSpeed = 0.4;    MAIN.PanelAnimationSpeed = 0.4;    MAIN.ZoomSpeed2D = 0.01;    MAIN.IdleTime = 0.75;    MAIN.TooltipCloseDistance = 30;    MAIN.InkOrWinTab = 1; /* Default use wacom wintab input. */    //display:    MAIN.FloatingAlpha = 0.35;    MAIN.SolidShadowLength = 20;    MAIN.WireColorSlices = 16;    MAIN.WireThickness = 5;    MAIN.WireSaggyness = 0.5;    laAddResourceFolder(".");    laSetMenuBarTemplates(laui_DefaultMenuButtons, laui_DefaultMenuExtras, "🧩LaGUI 2022");    laAddExtraExtension(LA_FILETYPE_UDF,"udf",0);    la_InitProgressWindow();    la_MakeTranslations();    //tns_RegisterResourcesForSoftwareRender();    la_RegisterDefaultSignals();    la_RegisterGeneralProps();    la_RegisterBuiltinTemplates();    la_RegisterMainThemes();    la_RegisterMainOperators();    la_RegisterMainUiTypes();    la_RegisterModellingOperators();    la_RegisterShapeOperators();    la_RegisterInternalProps();    la_RegisterAnimationResources();    la_RegisterWindowKeys();    if(MAIN.InitArgs.HasAudio) laInitAudio();    laFinalizeUiTemplates();    laFinalizeOperators();    la_RegisterControllerProps();    la_RefreshControllers();        la_RegisterBasicNodes();    tns_RegisterNodes();    la_InitThreadEnviornment();    laSetRootInstance(&MAIN);    if(!MAIN.DBInstMemLeft){ hsh65536Init(&MAIN.DBInstMemLeft); }    laPushDifferences(0, 0);    la_MakeDummyManagedUDF();    la_RegenerateWireColors();    laAnimationRegisterHolderPath("tns.world.root_objects_as_root");    logPrintNew("Initialization Completed\n");    MAIN.InitDone=1;    return 1;}int laGetReady(){    laInitArguments ia={0}; laSetDefaultInitArguments(&ia);    return laGetReadyWith(&ia);}void la_DestroyUiType(laUiType* uit);void la_FreeKeyMapItem(laKeyMapItem* kmi);void laShutoff(int SavePrefereces){    if(MAIN.SavePreferenceOnExit && SavePrefereces){ laSaveUserPreferences(); }    transDumpMissMatchRecord("TranslationDump.txt");    if(MAIN.Cleanup) MAIN.Cleanup();    if(MAIN.InitArgs.HasAudio) laDeinitAudio();    strSafeDestroy(&MAIN.WorkingDirectory);    strSafeDestroy(&MAIN.example_string);    la_NoLongerRecordUndo(); //XXX: it's not reliable yet, we need to only remove steps that are consistent with current data structure    // (Must undo/redo to desired position or delete from back/front without moving target head. This can be done but this is of lower priority. )    laWindow* wi; while(wi=lstPopItem(&MAIN.Windows)){ la_DestroyWindow(wi); }    laUiTemplate* uit; while(uit=lstPopItem(&MAIN.PanelTemplates)){ la_DestroyUiTemplate(uit); }    laCanvasTemplate* u2t; while(u2t=lstPopItem(&MAIN.View2DTemplates)){ la_DestroyCanvasTemplate(u2t); }    laUiType* uit1; while(uit1=lstPopItem(&MAIN.UiTypes)){ la_DestroyUiType(uit1); }    laOperatorType* at; for(int i=0;i<256;i++){ while(at=lstPopItem(&MAIN.OperatorTypeHash.Entries[i])) la_DestroyOperatorType(at); }    laSharedTypeItem* sti; while(sti=lstPopItem(&MAIN.SharedTypePointerSync)){ memFree(sti); }    laKeyMapItem* kmi; while(kmi=lstPopItem(&MAIN.KeyMap.Items)){ la_FreeKeyMapItem(kmi); }    laTheme* t; while(t=lstPopItem(&MAIN.Themes)){ la_DestroyTheme(t); }    arrFree(&MAIN.InputBuf,&MAIN.InputBufNext);    arrFree(&MAIN.InputBufU,&MAIN.InputBufUNext);    strSafeDestroy(&MAIN.CopyPending);    la_ClearUDFRegistryAndFolders();    laClearManagedUDF();    laClearSaveProp();    logClear();    tnsBindVertexArray(0); glDeleteVertexArrays(1,&MAIN.TempVAO);#ifdef __linux__    tnsContextMakeCurrent(0,0,0);    tnsDeleteContext(MAIN.glc);    #ifdef LA_USE_GLES        eglTerminate(MAIN.egl_dpy);    #endif#endif#ifdef _WIN32    tnsContextMakeCurrent(0,0,0);    tnsDeleteContext(MAIN.glc);    UnloadWintab();#endif    tnsQuit();    laPropContainer* pc; while(pc=lstPopItem(&MAIN.PropContainers)){ la_FreePropertyContainer(pc); }    //laPanel* p; while(p=lstPopItem(&MAIN.WastedPanels)){ memFree(p); }    strSafeDump();    hshFree(&MAIN.DBInstMemLeft);    memNoLonger();#ifdef LA_WITH_LUAJIT    lua_close(MAIN.L);#endif    printf("LaGUI has cleaned up.\n");}int laRestoreFactorySettings(){    char path[1024]; sprintf(path, "%s%s", MAIN.WorkingDirectory->Ptr, "preferences.udf");    if(remove(path)){ return 0; }    return 1;}void laSaveUserPreferences(){    char path[1024]; sprintf(path,"%s%s",MAIN.WorkingDirectory->Ptr,"preferences.udf");    laUDF* udf=laPrepareUDF(path);    laWriteProp(udf,"la.windows");    laWriteProp(udf,"la.user_preferences");    laWriteProp(udf,"la.input_mapping");    laWriteProp(udf,"la.controllers");    for(laListItemPointer* lip=MAIN.ExtraPreferencePaths.pFirst;lip;lip=lip->pNext){        laWriteProp(udf,lip->p);    }    laPackUDF(udf,0,0);}void laEnsureUserPreferences(){    char path[1024]; sprintf(path,"%s%s",MAIN.WorkingDirectory->Ptr,"preferences.udf");    laUDFRegistry* r=laFindUDFRegistry(path);    if(!r){ laSaveUserPreferences(); return; }    laUDF* udf=laOpenUDF(r->Path->Ptr,1,0,0); if(!udf){ logPrint("Can't read preferences. Using default settings."); return; }    laClearUDFRegistries();    while(MAIN.ResourceFolders.pFirst){ laRemoveResourceFolder(MAIN.ResourceFolders.pFirst); }    while(MAIN.InputMapping->InputMappings.pFirst){ laRemoveInputMapping(MAIN.InputMapping->InputMappings.pFirst); }    laExtractUDF(udf,0,LA_UDF_MODE_OVERWRITE);    laCloseUDF(udf);    la_RemoveDuplicatedScreenConf();    la_RemoveDuplicatedControllers();    laRefreshUDFRegistries();    //restore forced settings    if(MAIN.InitArgs.EnableLogStdOut){ MAIN.EnableLogStdOut=1; }}void laAddExtraExtension(int FileType, ...){    va_list list; va_start(list,FileType);    char* ext;    while(ext=va_arg(list,char*)){ if(!ext) break;        laExtensionType* et=memAcquireSimple(sizeof(laExtensionType));        et->FileType=FileType; et->Extension=ext;        lstAppendItem(&MAIN.ExtraExtensions, et);    }    va_end(list);}void laAddExtraPreferencePath(const char* path){    if(!path) return;    lstAppendPointer(&MAIN.ExtraPreferencePaths, path);}void laAddExtraPreferencePage(const char* name, laUiDefineFunc Func){    if(!name || !Func) return;    laExtraPreferencePage*epp=memAcquireSimple(sizeof(laExtraPreferencePage));    epp->Name=name; epp->Func=Func; lstAppendItem(&MAIN.ExtraPreferencePages,epp);}void laSetMenuBarTemplates(laUiDefineFunc MenuButtons, laUiDefineFunc MenuExtras, const char* ProgramName){    MAIN.MenuButtons=MenuButtons; MAIN.MenuExtras=MenuExtras; MAIN.MenuProgramName=ProgramName;}void laSetAboutTemplates(laUiDefineFunc AboutContent, laUiDefineFunc AboutVersion, laUiDefineFunc AboutAuthor){    MAIN.AboutAuthor=AboutAuthor; MAIN.AboutVersion=AboutVersion; MAIN.AboutContent=AboutContent;}void laSetPreferenceTemplates(laUiDefineFunc PreferencePageDisplay, laUiDefineFunc PreferencePageInput, laUiDefineFunc PreferencePageResource, laUiDefineFunc PreferencePageTheme){    MAIN.PreferencePageDisplay=PreferencePageDisplay; MAIN.PreferencePageInput=PreferencePageInput;    MAIN.PreferencePageResource=PreferencePageResource; MAIN.PreferencePageTheme=PreferencePageTheme;}laCustomSignal* laFindSignal(char* Name){    for(laCustomSignal* cs=MAIN.CustomSignals.pFirst;cs;cs=cs->Item.pNext){ if(strSame(SSTR(cs->Name),Name)) return cs; }    return 0;}void laInputMappingUpdateSignal(laInputMappingEntry* ime){    if(ime->DeviceType == LA_INPUT_DEVICE_KEYBOARD){ char* str=SSTR(ime->Key); if(str&&str[0]){ int adv; ime->KeyValue=laToUnicode(str,&adv); }else{ ime->KeyValue=0; } }    if(ime->DeviceType == LA_INPUT_DEVICE_JOYSTICK){ int key=0; sscanf(SSTR(ime->Key),"%d",&key); ime->KeyValue=key; }    char* signal = SSTR(ime->Signal);    laCustomSignal *cs=laFindSignal(signal); if(cs){ ime->SignalValue=cs->Signal; }else{ ime->SignalValue=0;}}laInputMapping* laNewInputMapping(char* Name){    laInputMapping* im=memAcquireHyper(sizeof(laInputMapping)); lstAppendItem(&MAIN.InputMapping->InputMappings,im);    memAssignRef(MAIN.InputMapping,&MAIN.InputMapping->CurrentInputMapping,im);    strSafeSet(&im->Name,Name);    return im;}laInputMappingEntry* laNewInputMappingEntry(laInputMapping* im, int DeviceType, int JoystickDevice, char* Key, int SpecialKeyBit, char* Signal){    laInputMappingEntry* e=memAcquire(sizeof(laInputMappingEntry)); lstAppendItem(&im->Entries,e);    e->DeviceType = DeviceType; e->JoystickDevice=JoystickDevice; e->SpecialKeyBits=SpecialKeyBit;    memAssignRef(e,&e->Parent,im);    if(Signal){ strSafeSet(&e->Signal,Signal); } if(Key){ strSafeSet(&e->Key,Key); }    laInputMappingUpdateSignal(e);}void laRemoveInputMappingEntry(laInputMapping* im, laInputMappingEntry* e){    memAssignRef(e,&e->Parent,0); lstRemoveItem(&im->Entries,e); strSafeDestroy(&e->Signal); strSafeDestroy(&e->Key); memFree(e);}void laRemoveInputMapping(laInputMapping* im){    laInputMappingEntry* e; while(e=im->Entries.pFirst){ laRemoveInputMappingEntry(im,e); }    laInputMapping* use=im->Item.pNext?im->Item.pNext:im->Item.pPrev;    memAssignRef(MAIN.InputMapping,&MAIN.InputMapping->CurrentInputMapping,use);    lstRemoveItem(&MAIN.InputMapping->InputMappings,im); strSafeDestroy(&im->Name); memFree(im);}laCustomSignal* laNewCustomSignal(char* Name, int Signal){    laCustomSignal* cs=memAcquire(sizeof(laCustomSignal)); lstAppendItem(&MAIN.CustomSignals,cs);    strSafeSet(&cs->Name,Name); cs->Signal = Signal;    return cs;}void laRemoveCustomSignal(laCustomSignal* cs){    strSafeDestroy(&cs->Name); lstRemoveItem(&MAIN.CustomSignals,cs); memFree(cs);}void la_SendSignalsFromEvent(laEvent* e){    laInputMapping* im = MAIN.InputMapping->CurrentInputMapping;    if(!im){return;}    for(laInputMappingEntry* ime = im->Entries.pFirst;ime;ime=ime->Item.pNext){        if(e->type==LA_KEY_DOWN && ime->DeviceType == LA_INPUT_DEVICE_KEYBOARD){            if(e->key == ime->KeyValue && e->SpecialKeyBit == ime->SpecialKeyBits){                la_SendSignalEvent(e->window->win,ime->SignalValue);            }        }    }}//MSG====================================================int la_IsThisSysWindow(laWindow *wnd, SYSWINDOW hwnd){    if (wnd->win == hwnd) return 1;    else return 0;};void la_EnsurePanelSnapping(laPanel *p, int CW, int CH){    if (p->SL){ int s=p->SL<0?0:p->SL;        if (p->TX != s) laRecalcPanel(p);        p->TX = s;    }    if (p->SR){ int s=p->SR<0?0:p->SR;        if (p->TW != CW - p->TX - s) laRecalcPanel(p);        p->TW = CW - p->TX - s;    }    if (p->ST){ int s=p->ST<0?0:p->ST;        if (p->TY != s) laRecalcPanel(p);        p->TY = s;    }    if (p->SB){ int s=p->SB<0?0:p->SB;        if (p->TH != CH - p->TY - s) laRecalcPanel(p);        p->TH = CH - p->TY - s;    }}void la_RecalcBlockRecursive(laBlock *b, int X, int Y, int W, int H){    laPanel *p = 0;    b->X = X;    b->Y = Y;    b->W = W;    b->H = H;    if (b->B1){        int SplitWidth;        if (b->Vertical){            SplitWidth = H * b->SplitRatio;            la_RecalcBlockRecursive(b->B1, X, Y, W, SplitWidth);            la_RecalcBlockRecursive(b->B2, X, Y + SplitWidth, W, H - SplitWidth);        }else{            SplitWidth = W * b->SplitRatio;            la_RecalcBlockRecursive(b->B1, X, Y, SplitWidth, H);            la_RecalcBlockRecursive(b->B2, X + SplitWidth, Y, W - SplitWidth, H);        }    }    //if (!b->CurrentPanel)b->CurrentPanel = b->Panels.pFirst;    for(p=b->Panels.pFirst;p;p=p->Item.pNext){        p->TitleWidth = tnsStringGetWidth(transLate(p->Title->Ptr), 0, 0);    }    if (p = b->CurrentPanel){        int TitleGap=b->Folded?0:LA_RH;        p->X = X + LA_SEAM_W; p->Y = Y + LA_SEAM_W + TitleGap;        p->TX = X + LA_SEAM_W; p->TY = Y + LA_SEAM_W + TitleGap;        p->TW = W - LA_SEAM_W*2; p->TH = H - LA_SEAM_W*2 - TitleGap;        laRecalcPanel(p);    }}void la_UpdateUiPlacement(laWindow *w){    laLayout *l;    laPanel *p;    int CW = w->CW;    int CH = w->CH;    laBoxedTheme* bt = _LA_THEME_FLOATING_PANEL;    int MenuHeight=(bt->TM+bt->BM)*2+LA_RH;    if(w->MaximizedUi && w->MaximizedUiPanel){        laRecalcPanel(w->MaximizedUiPanel);    }elif(w->MaximizedBlock){        la_RecalcBlockRecursive(w->MaximizedBlock, -LA_SEAM_W, MenuHeight, CW+LA_SEAM_W*2, CH-MenuHeight+LA_SEAM_W);    }else{        for (l = w->Layouts.pFirst; l; l = l->Item.pNext){            la_RecalcBlockRecursive(l->FirstBlock, -LA_SEAM_W, MenuHeight, CW+LA_SEAM_W*2, CH-MenuHeight+LA_SEAM_W);        }    }    for (p = w->Panels.pFirst; p; p = p->Item.pNext){        if(p->IsMenuPanel){            p->TH=p->H=MenuHeight;        }        la_EnsurePanelSnapping(p, CW, CH);        laRecalcPanel(p);    }}void la_CommandResizeWindow(SYSWINDOW hwnd, int x, int y, int w, int h){    laWindow *window = lstFindItem(hwnd, la_IsThisSysWindow, &MAIN.Windows);    if (!window) return;#ifdef _WIN32    RECT rcc; GetClientRect(window->win, &rcc);    RECT rcw; GetWindowRect(window->win, &rcw);    window->CW = rcc.right - rcc.left;    window->CH = rcc.bottom - rcc.top;    window->W = rcw.right - rcw.left;    window->H = rcw.bottom - rcw.top;    window->X = rcw.left; window->Y = rcw.top;#endif#ifdef __linux__    XWindowAttributes attr;    XGetWindowAttributes(MAIN.dpy, window->win, &attr);    window->CW = w; window->CH = h;    window->W = w; window->H = h;    window->X = x; window->Y = y;    if(MAIN.AutoSwitchColorSpace){        laScreen* s = laGetWindowScreen(window);        if(s){ window->OutputColorSpace = s->ColorSpace; }    }#endif    la_UpdateUiPlacement(window);}int la_OnWindowDestroy(SYSWINDOW wnd){    laListHandle *hlst = &MAIN.Windows;    laWindow *w = lstFindItem(wnd, la_IsThisSysWindow, hlst);    if (!w) return 0;    if (MAIN.Windows.pFirst==MAIN.Windows.pLast){        int empty=0; int mod=laRegisterModifications(1,1,&empty,0);        if(mod || empty){ laInvoke(0, "LA_managed_save", 0,0,"on_exit=true;",0); return 0; }        laShutoff(1);        return 1;    }    laListHandle h={0};laLayout*l=0;    while(l=lstPopItem(&w->Layouts)){ lstAppendItem(&h, l); }    la_DestroyWindow(w);    int done=0; for(laWindow* w=MAIN.Windows.pFirst;w;w=w->Item.pNext){#ifdef __linux__        if(done) glXSwapIntervalEXTF(MAIN.dpy, w->win, 0);        else { glXSwapIntervalEXTF(MAIN.dpy, w->win, 1); done = 1; }#endif        while (l = lstPopItem(&h)) { lstAppendItem(&w->Layouts, l); }    }    return 0;}void la_MakeSpecialKeyBit(SYSWINDOW hwnd,laWindow*wnd,laEvent *e,int use_last_pos){    laListHandle *el = &wnd->EventList;    laEvent* last_e=el->pLast;    SYSWINDOW root_ret, win_ret; int rrx=0,rry=0,rx=e->x,ry=e->y,rmask=0;#ifdef __linux__    XQueryPointer(MAIN.dpy, wnd->win, &root_ret,&win_ret,&rrx,&rry,&rx,&ry,&rmask);    e->SpecialKeyBit = ((rmask&ShiftMask)?LA_KEY_SHIFT:0)|((rmask&ControlMask)?LA_KEY_CTRL:0)|((rmask&Mod1Mask)?LA_KEY_ALT:0);#endif#ifdef _WIN32    e->SpecialKeyBit = ((GetKeyState(VK_SHIFT)&0x8000)?LA_KEY_SHIFT:0)|((GetKeyState(VK_CONTROL)&0x8000)?LA_KEY_CTRL:0)|((GetKeyState(VK_MENU)&0x8000)?LA_KEY_ALT:0);#endif}void la_SaveEvent(SYSWINDOW hwnd, laEvent *e, int use_last_pos){    laListHandle *wl = &MAIN.Windows;    laWindow* wnd = lstFindItem(hwnd, la_IsThisSysWindow, wl);    if (!wnd){ memFree(e); return; }    laListHandle *el = &wnd->EventList;    la_MakeSpecialKeyBit(hwnd,wnd,e,use_last_pos);    if(use_last_pos){ e->x=MAIN.evLastX; e->y=MAIN.evLastY; }    e->window = wnd;    e->Twist=MAIN.StylusTwist; e->HasTwist = MAIN.StylusHasTwist;    e->Pressure=MAIN.IsPen?(MAIN.PointerIsEraser?MAIN.EraserPressure:MAIN.StylusPressure):0.5f;    e->Orientation=MAIN.PointerIsEraser?MAIN.EraserOrientation:MAIN.StylusOrientation;    e->Deviation=MAIN.PointerIsEraser?MAIN.EraserDeviation:MAIN.StylusDeviation;    e->IsEraser=MAIN.PointerIsEraser;    e->GoodPressure=MAIN.IsPen;    lstAppendItem(el, (laListItem *)e);    laMappingRequestEval();};void la_SendKeyboardEvent(SYSWINDOW hwnd, int type, int key){    laEvent *e = memAcquireSimple(sizeof(laEvent)); e->type = type; e->key = tolowerGuarded(key);    la_SaveEvent(hwnd, e, 1);};void la_SendInputEvent(SYSWINDOW hwnd, uint32_t Input){    laEvent *e = memAcquireSimple(sizeof(laEvent));    e->type = LA_INPUT; e->Input=Input;    la_SaveEvent(hwnd, e, 1);}void la_SendEmptyEvent(SYSWINDOW hwnd){    laEvent *e = memAcquireSimple(sizeof(laEvent));    e->type = LA_EMPTY;    la_SaveEvent(hwnd, e, 1);}void laSendOperatorTriggerEvent(){    if (MAIN.ReTriggerOperators) la_SendEmptyEvent(MAIN.CurrentWindow->win);    MAIN.ReTriggerOperators = 0;}int la_TranslateSpecialKey(int keysym){#ifdef __linux__    switch(keysym){    case XK_Return:    return LA_KEY_ENTER;    case XK_BackSpace: return LA_KEY_BACKSPACE;    case XK_Delete:    return LA_KEY_DELETE;    case XK_Escape:    return LA_KEY_ESCAPE;    case XK_Tab:       return LA_KEY_TAB;    case XK_Left:      return LA_KEY_ARRLEFT;    case XK_Right:     return LA_KEY_ARRRIGHT;    case XK_Up:        return LA_KEY_ARRUP;    case XK_Down:      return LA_KEY_ARRDOWN;    case XK_Control_L: return LA_KEY_CTRL;    case XK_Control_R: return LA_KEY_CTRL;    case XK_Shift_L:   return LA_KEY_SHIFT;    case XK_Shift_R:   return LA_KEY_SHIFT;    case XK_Alt_L:     return LA_KEY_ALT;    case XK_Alt_R:     return LA_KEY_ALT;    default:           return keysym;    }#endif#ifdef _WIN32    switch (keysym) {    case VK_RETURN:    return LA_KEY_ENTER;    case VK_ESCAPE:    return LA_KEY_ESCAPE;    case VK_TAB:       return LA_KEY_TAB;    case VK_LEFT:      return LA_KEY_ARRLEFT;    case VK_RIGHT:     return LA_KEY_ARRRIGHT;    case VK_UP:        return LA_KEY_ARRUP;    case VK_DOWN:      return LA_KEY_ARRDOWN;    case VK_CONTROL:   return LA_KEY_CTRL;    case VK_SHIFT:     return LA_KEY_SHIFT;    case VK_MENU:      return LA_KEY_ALT;    case VK_OEM_1:     return ';';    case VK_OEM_2:     return '/';    case VK_OEM_3:     return '`';    case VK_OEM_4:     return '[';    case VK_OEM_5:     return '\\';    case VK_OEM_6:     return ']';    case VK_OEM_7:      return '\'';    default:           return keysym;    }#endif}void la_SendMouseEvent(SYSWINDOW hwnd, int type, int x, int y){    //if((type&LA_STATE_DOWN)&&(x!=MAIN.evLastX || y!=MAIN.evLastY)){    //    laEvent *e = memAcquireSimple(sizeof(laEvent));    //    e->Type = LA_MOUSEMOVE; e->x = x; e->y = y;    //    la_SaveEvent(hwnd, e, 0);    //}    laEvent *e = memAcquireSimple(sizeof(laEvent));    e->type = type; e->x = x; e->y = y;    la_SaveEvent(hwnd, e, 0);    MAIN.evLastX=x; MAIN.evLastY=y;};void la_SendTimerEvent(SYSWINDOW hwnd, int type){    laEvent *e = memAcquireSimple(sizeof(laEvent));    e->type = type;    la_SaveEvent(hwnd, e, 1);};void la_SendSignalEvent(SYSWINDOW* hwnd, int signal){    laEvent *e = memAcquireSimple(sizeof(laEvent));    e->type = LA_SIGNAL_EVENT;    e->key = signal;    la_SaveEvent(hwnd, e, 1);};void laRetriggerOperators(){    MAIN.ReTriggerOperators = 1;}void laSetFrameCallbacks(laPreFrameF PreFrame, laPreDrawF PreDraw, laPostFrameF PostFrame){    MAIN.PreFrame=PreFrame; MAIN.PreDraw=PreDraw; MAIN.PostFrame=PostFrame;}void laSetCleanupCallback(laCleanupF Cleanup){    MAIN.Cleanup=Cleanup;}void laSetInputProcessCallback(laInputProcessF InputProcess){    MAIN.InputProcess=InputProcess;}//====================================================================================================void la_DestroyTheme(laTheme* t){    laBoxedTheme*bt; while(bt=lstPopItem(&t->BoxedThemes)){ strSafeDestroy(&bt->Name); *bt->BackRef=0; memFree(bt); }    strSafeDestroy(&t->Name);    strSafeDestroy(&t->Author);}laTheme *laDesignTheme(const char *Name, const char *AuthorName){    laTheme *t = memAcquireHyper(sizeof(laTheme));    strSafeSet(&t->Name, Name);    strSafeSet(&t->Author, AuthorName);    lstAppendItem(&MAIN.Themes, t);    MAIN.CurrentTheme = t;    return t;}laBoxedTheme *laDesignBoxedTheme(laTheme *t, const char *Name, laBoxedTheme** BackRef,                                 real NormalY,real ActiveY,real BorderY,real TextY,real TextActiveY, real Alpha,                                 real LeftMargin,  real RightMargin,  real TopMargin,  real BottomMargin,                                 real LeftPadding, real RightPadding, real TopPadding, real BottomPadding){    laBoxedTheme *bt = memAcquire(sizeof(laBoxedTheme));    strSafeSet(&bt->Name, Name);    bt->NormalY=NormalY;    bt->ActiveY=ActiveY;    bt->BorderY=BorderY;    bt->TextY=TextY; bt->TextActiveY=TextActiveY; bt->Alpha = Alpha;    bt->Margins[0] = LeftMargin;   bt->Margins[1] = RightMargin;   bt->Margins[2] = TopMargin;   bt->Margins[3] = BottomMargin;    bt->Paddings[0] = LeftPadding; bt->Paddings[1] = RightPadding; bt->Paddings[2] = TopPadding; bt->Paddings[3] = BottomPadding;    bt->BackRef = BackRef;    lstAppendItem(&t->BoxedThemes, bt);    return bt;}laTheme *laGetTheme(const char *ThemeName){    laTheme *t = MAIN.Themes.pFirst;    for (t; t; t = t->Item.pNext){        if (strSame(t->Name->Ptr, ThemeName)) return t;    }    return 0;}laBoxedTheme *laGetBoxedTheme(const char *ThemeName, const char *BoxName){    laTheme *t = MAIN.Themes.pFirst;    for (t; t; t = t->Item.pNext){        laBoxedTheme *bt;        if (!strSame(t->Name->Ptr, ThemeName)) continue;        bt = t->BoxedThemes.pFirst;        for (bt; bt; bt = bt->Item.pNext){            if (strSame(bt->Name->Ptr, BoxName)) return bt;        }    }    return 0;}real* laThemeColor(laBoxedTheme* bt, int which){    switch(which){        default:        case LA_BT_NORMAL: return bt->Normal;        case LA_UI_EDITING:        case LA_BT_ACTIVE: return bt->Active;        case LA_BT_BORDER: return bt->Border;        case LA_BT_TEXT:   return bt->Text; break;        case LA_BT_TEXT_ACTIVE: return bt->TextActive; break;        case LA_BT_DISABLED: return bt->Inactive; break;        case LA_BT_DISABLED|LA_BT_TEXT: return bt->TextInactive; break;    }    return bt->Normal;}real* laAccentColor(int which){    switch(which){        default:        case LA_BT_NORMAL: case LA_UI_EDITING: case LA_BT_ACTIVE: return MAIN.CurrentTheme->SelectionColor;        case LA_BT_BORDER: case LA_BT_TEXT: case LA_BT_TEXT_ACTIVE: return MAIN.CurrentTheme->CursorColor;        case LA_BT_VERTEX: return MAIN.CurrentTheme->VertexColor;        case LA_BT_FACE:        case LA_BT_EDGE: return MAIN.CurrentTheme->EdgeColor;        case LA_BT_SVERTEX: return MAIN.CurrentTheme->SVertexColor;        case LA_BT_SEDGE: return MAIN.CurrentTheme->SEdgeColor;        case LA_BT_SFACE: return MAIN.CurrentTheme->SFaceColor;    }    return MAIN.CurrentTheme->SelectionColor;}void la_RefreshBoxedThemeColor(laBoxedTheme* bt){    real hcy[3];    tnsRGB2HCY(MAIN.CurrentTheme->Color,hcy);    hcy[2]=bt->NormalY; tnsHCY2RGB(hcy, bt->Normal); bt->Normal[3]=bt->Alpha;    hcy[2]=bt->ActiveY; tnsHCY2RGB(hcy, bt->Active); bt->Active[3]=bt->Alpha;    hcy[2]=bt->BorderY; tnsHCY2RGB(hcy, bt->Border); bt->Border[3]=1;    hcy[2]=bt->TextY;   tnsHCY2RGB(hcy, bt->Text); bt->Text[3]=1;    hcy[2]=bt->TextActiveY; tnsHCY2RGB(hcy, bt->TextActive); bt->TextActive[3]=1;    int *tm=&bt->LM,*tp=&bt->LP;    for(int i=0;i<4;i++){        tm[i]=(real)bt->Margins[i]*LA_RH*MAIN.MarginSize/10+0.5;        tp[i]=(real)bt->Paddings[i]*LA_RH*MAIN.MarginSize/10+0.5;    }}void la_RefreshThemeColorSelf(laTheme* th){    tnsVectorCopy3d(th->AccentColor, th->CursorColor);   th->CursorColor[3]=th->CursorAlpha;    tnsVectorCopy3d(th->AccentColor, th->SelectionColor);th->SelectionColor[3]=th->SelectionAlpha;    real hcy[3], usehcy[3];    tnsRGB2HCY(th->Color,hcy); tnsVectorCopy3d(hcy,usehcy);    usehcy[2]=th->VertexBrightness; tnsHCY2RGB(usehcy, th->VertexColor); th->VertexColor[3]=th->VertexTransparency;    usehcy[2]=th->EdgeBrightness;   tnsHCY2RGB(usehcy, th->EdgeColor);   th->EdgeColor[3]=th->EdgeTransparency;    tnsVectorCopy3d(th->AccentColor, th->SVertexColor); th->SVertexColor[3]=th->SelectedVertexTransparency;    tnsVectorCopy3d(th->AccentColor, th->SEdgeColor); th->SEdgeColor[3]=th->SelectedEdgeTransparency;    tnsVectorCopy3d(th->AccentColor, th->SFaceColor); th->SFaceColor[3]=th->SelectedFaceTransparency;}void la_RefreshThemeColor(laTheme* th){    real hcy[3], usehcy[3], normalhcy[3];    tnsRGB2HCY(th->Color,hcy);    la_RefreshThemeColorSelf(th);    for(laBoxedTheme* bt = th->BoxedThemes.pFirst;bt;bt=bt->Item.pNext){        la_RefreshBoxedThemeColor(bt);        (*bt->BackRef) = bt;        tnsRGB2HCY(bt->Text, usehcy); usehcy[1]*=th->InactiveSaturation;        tnsHCY2RGB(usehcy, bt->TextInactive); bt->TextInactive[3]=th->InactiveMix;        tnsRGB2HCY(bt->Normal, normalhcy); normalhcy[1]*=th->InactiveSaturation;        tnsHCY2RGB(normalhcy, bt->Inactive); bt->Inactive[3]=bt->Alpha*th->InactiveMix;    }}//I FUCKING HATE THIS STUPID FUNCTIONint la_SetUpUiListMatrix(laUiListDraw *uild, laUiList *Target, int _L, int _R, int LimH, int PanelH, int GlobalX, int GlobalY){    laUiListDrawItem *uildi = memAcquireSimple(sizeof(laUiListDrawItem));    laUiListDrawItem *last = uild->Items.pFirst;    int LimW=_R-_L;    int SL, SR, SU, SB;    int Target__B = Target->B;    int Target__R = Target->R;    uildi->Target = Target;    //if (Target__B - Target->U > LimH) Target__B = Target->U + LimH;    if (Target__R - Target->L > LimW) Target__R = Target->L + LimW;    uildi->XP = last ? last->XP + Target->PanX : Target->PanX;    uildi->YP = last ? last->YP + Target->PanY : Target->PanY;    uildi->L = last ? Target->L - last->XP : Target->L;    uildi->R = last ? Target__R - last->XP : Target__R;    uildi->U = last ? Target->U - last->YP : Target->U;    uildi->B = last ? Target__B - last->YP : Target__B;    if (uildi->B - uildi->U > LimH) uildi->B = Target->U + LimH;    uildi->L -= GlobalX;    uildi->R -= GlobalX;    uildi->U -= GlobalY;    uildi->B -= GlobalY;    SL = last ? (uildi->L < last->L ? last->L : uildi->L) : uildi->L;    SR = last ? (uildi->R > last->R ? last->R : uildi->R) : uildi->R;    SU = last ? (uildi->U < last->U ? last->U : uildi->U) : uildi->U;    SB = last ? (uildi->B > last->B ? last->B : uildi->B) : uildi->B;    uildi->DifX = SL - uildi->L;    uildi->DifY = SU - uildi->U;    uildi->L = SL;    uildi->R = SR+uildi->DifX;    uildi->U = SU;    uildi->B = SB;//+uildi->DifY;    if(uildi->R>_R){ uildi->R=_R; }    if(uildi->B-SU>LimH){ uildi->B=SU+LimH; }    //printf("py %f %d lb %d b %d limh %d sb%d\n",Target->PanY,uildi->U,last?last->B:0,uildi->B,LimH,SB);    if(uildi->R - uildi->L<=0 || uildi->B - uildi->U<=0){        memFree(uildi);        return 0;    }    tnsViewportWithScissor(uildi->L-1, PanelH - uildi->B, uildi->R - uildi->L+1, uildi->B - uildi->U-1);    tnsOrtho(Target->L + Target->PanX + uildi->DifX-1,             Target->L + Target->PanX + uildi->DifX+1+ (uildi->R - uildi->L),             Target->U + Target->PanY + uildi->DifY+ (uildi->B - uildi->U),             Target->U + Target->PanY + uildi->DifY+1,             -100, 100);    lstPushItem(&uild->Items, uildi);    return 1;}void la_SetUpUiListMatrixInLine(laUiListDraw *uild, int L, int R, int U, int B, int PanX, int PanY, int LimH, int PanelH){    laUiListDrawItem *uildi = memAcquireSimple(sizeof(laUiListDrawItem));    laUiListDrawItem *last = uild->Items.pFirst;    int SL, SR, SU, SB;    if (B - U > LimH) B = U + LimH;    uildi->XP = last ? last->XP + PanX : PanX;    uildi->YP = last ? last->YP + PanY : PanY;    uildi->L = last ? L - last->XP : L;    uildi->R = last ? R - last->XP : R;    uildi->U = last ? U - last->YP : U;    uildi->B = last ? B - last->YP : B;    SL = last ? (uildi->L < last->L ? last->L : uildi->L) : uildi->L;    SR = last ? (uildi->R > last->R ? last->R : uildi->R) : uildi->R;    SU = last ? (uildi->U < last->U ? last->U : uildi->U) : uildi->U;    SB = last ? (uildi->B > last->B ? last->B : uildi->B) : uildi->B;    uildi->DifX = SL - uildi->L;    uildi->DifY = SU - uildi->U;    uildi->L = SL;    uildi->R = SR;    uildi->U = SU;    uildi->B = SB;    tnsViewportWithScissor(uildi->L, PanelH - uildi->B, uildi->R - uildi->L, uildi->B - uildi->U);    tnsOrtho(L + PanX + uildi->DifX,             L + PanX + uildi->DifX + (uildi->R - uildi->L),             U + PanY + uildi->DifY + (uildi->B - uildi->U),             U + PanY + uildi->DifY,             -100, 100);    lstPushItem(&uild->Items, uildi);}void la_DoUiScissor(laUiItem* ui, int* savex, int* savey, int* savew, int* saveh,    int* savel, int* saver, int* saveu, int* saveb){    laPanel* panel=MAIN.PropMatcherContextP; int PW=panel->W, PH=panel->H;    *savex=T->vsx;*savey=T->vsy;*savew=T->vsw;*saveh=T->vsh;    *savel=T->vol;*saver=T->vor;*saveu=T->vou;*saveb=T->vob;    real p[3]={0}, tp[3]={0}; tnsMatrix44d m; tnsGetMVPMatrix(m);    real x,y,w,h;    x=TNS_MAX2(ui->L,T->vsx); y=TNS_MAX2(PH-ui->B,T->vsy);    w=TNS_MIN2(ui->R-ui->L,T->vsw); h=TNS_MIN2(ui->B-ui->U,T->vsh);    tnsViewportWithScissor(x,y,w,h); tnsOrtho(ui->L,ui->R,ui->B,ui->U,-100,100);}void la_RebuildCurrentUiListMatrix(laUiListDraw *uild, laUiList *Target, int LimH, int PanelH){    laUiListDrawItem *uildi = uild->Items.pFirst;    tnsViewportWithScissor(uildi->L-1, PanelH - uildi->B-1, uildi->R - uildi->L+2, uildi->B - uildi->U+2);    tnsOrtho(Target->L + Target->PanX + uildi->DifX -1,             Target->L + Target->PanX + uildi->DifX +1 + (uildi->R - uildi->L),             Target->U + Target->PanY + uildi->DifY +1 + (uildi->B - uildi->U),             Target->U + Target->PanY + uildi->DifY -1,             -100, 100);}void la_RestoreLastUiListMatrix(laUiListDraw *uild, int PanelH){    laUiListDrawItem *uildi = lstPopItem(uild);    laUiList *Target;    memFree(uildi);    uildi = uild->Items.pFirst;    if (!uildi || !uildi->Target){        if (uild->Items.pFirst) la_RestoreLastUiListMatrix(uild, PanelH);        return;    }    Target = uildi->Target;    tnsViewportWithScissor(uildi->L-1, PanelH - uildi->B-1, uildi->R - uildi->L+2, uildi->B - uildi->U+2);    tnsOrtho(Target->L + Target->PanX + uildi->DifX -1,             Target->L + Target->PanX + uildi->DifX +1 + (uildi->R - uildi->L),             Target->U + Target->PanY + uildi->DifY +1 + (uildi->B - uildi->U),             Target->U + Target->PanY + uildi->DifY -1,             -100, 100);}void la_SetupUiListLimitMatrix(laUiListDraw *uild, int L, int R, int U, int B, int PanelH){    laUiListDrawItem *uildi = memAcquireSimple(sizeof(laUiListDrawItem));    uildi->L = L;    uildi->R = R;    uildi->U = U;    uildi->B = B;    tnsViewportWithScissor(uildi->L, PanelH - uildi->B, uildi->R - uildi->L, uildi->B - uildi->U);    tnsOrtho(L, R, B, U, -100, 100);    lstPushItem(&uild->Items, uildi);}void la_ClearUiListMatrix(laUiListDraw *uild){    laUiListDrawItem *uildi;    while (uildi = lstPopItem(uild)){        memFree(uildi);    }}int la_UpdateUiListRecursive(laUiList *uil, int U, int L, int R, int B, int Fast, laPanel *ParentPanel);int la_DrawUiListRecursive(laUiListDraw *uild, laUiList *uil, int L, int R, int U, int B, int LimH, int ConditionStackLevel, int GlobalX, int GlobalY, int RegisterNodes);void la_DestroyUiList(laUiList *uil, int NoFree, int RemoveUsers, int OnlyRemoveUser);void la_DrawUiListScrollerV(laUiList *uil, int DisplayOffset, int TotalH, int DisplayH, int UiR);int la_TestUiListMinumWidth(laUiList *uil);void la_PanelValidateWidth(laPanel *p, laUiList *ui){    if (ui){        if (p->MaxW && p->TW > p->MaxW) p->TW = p->MaxW;        if (p->MinW && p->TW < p->MinW) p->TW = p->MinW;        la_EnsurePanelSnapping(p, MAIN.CurrentWindow->CW, MAIN.CurrentWindow->CH);        p->X = p->TX; p->Y = p->TY;        p->W = p->TW;    }}void laEnsurePanelInBound(laPanel *p, laUiList *uil){    int cw = MAIN.CurrentWindow->CW;    int ch = MAIN.CurrentWindow->CH;    int PH = p->TH;    laBoxedTheme*bt = *p->BT;    int uih=uil->B + bt->BM;    if (p->BoundUi && !(p->SB||p->ST)) PH = TNS_MAX2(uih, p->MinH);    if (p->MaxH && PH > p->MaxH) p->TH = p->MaxH;    else if (p->MinH && PH < p->MinH) p->TH = p->MinH;    else p->TH = PH;    p->H = p->TH;    if(p->BoundUi){        if ((p->X + p->W) > cw) p->X -= (p->X + p->W - cw);        if ((p->Y + p->H) > ch) p->Y -= (p->Y + p->H - ch);        if (p->X < 0) p->X = 0;        if (p->Y < 0) p->Y = 0;        if ((p->X + p->W) > cw){ p->W -= (p->X + p->W - cw); }        if ((p->Y + p->H) > ch){ p->H -= (p->Y + p->H - ch); }    }else{        if (p->Y < 0) p->Y = 0;        if ((!p->Block)&&(!p->IsMenuPanel)){            int cw2=cw-LA_RH*2,ch2=ch-LA_RH*2;            if (p->X + p->W < LA_RH * 5) p->X = LA_RH * 5 - +p->W;            if (p->X > cw2){ p->X = cw2; } if (p->Y > ch2){ p->Y = ch2; }            if (p->W > cw2){ p->W = cw2; } if (p->H > ch2){ p->H = ch2; }        }    }    if((!p->IsMenuPanel) && (p->Mode!=LA_PANEL_FLOATING_PASSIVE)){        if(p->W<LA_RH*4) p->W=LA_RH*4;        if(p->H<LA_RH*2) p->H=LA_RH*2;    }    if (p->ST) p->TY = p->ST;    if (p->SB && p->TH != ch - p->TY - p->SB) laRecalcPanel(p);    if (p->SB) p->TH = ch - p->TY - p->SB;    if(p->CloseWhenMovedOut==2){ p->X=(cw-p->W)/2; p->Y=(ch-p->H)/2; }    p->TX = p->X; p->TY = p->Y;    p->TW = p->W; p->TH = p->H;}void laPlacePanelForCreation(laPanel *p){    int cw = MAIN.CurrentWindow->CW; int ch = MAIN.CurrentWindow->CH; int PH = p->TH;    if ((!p->Block)&&(!p->IsMenuPanel)&&(!p->Parent)){        if (p->X+p->W > cw-LA_RH){ p->X = cw-LA_RH-p->W; }        if (p->Y+p->H > ch-LA_RH){ p->Y = ch-LA_RH-p->H; }        if (p->X < LA_RH){ p->X = LA_RH; } if (p->Y < LA_RH){ p->Y = LA_RH; }        p->TX=p->X; p->TY=p->Y;    }}void la_SetPanelMatrix(laPanel *p, laBoxedTheme *bt){    tnsDrawToOffscreen(p->OffScr, 1, 0);    tnsViewportWithScissor(0, 0, p->W, p->H);    //tnsMatrixMode(TNS_PROJECTION_MATRIX);    tnsOrtho(0, p->W, p->H, 0, -100, 100);}void la_SetPanelMatrixDrawWindow(laPanel *p, laBoxedTheme *bt){    tnsDrawToScreen();    tnsViewportWithScissor(p->X, MAIN.CurrentWindow->CH - p->H - p->Y, p->W, p->H);    tnsOrtho(0, p->W, p->H, 0, -100, 100);}void la_SetPanelMatrixLRTB(int PW, int PH, int LPadding, int RPadding, int TPadding, int BPadding, int XOffset, int YOffset){    tnsViewportWithScissor(LPadding, BPadding, PW - LPadding - RPadding, PH - TPadding - BPadding);    tnsOrtho(XOffset, XOffset + PW - LPadding - RPadding, YOffset + PH - BPadding, YOffset + TPadding, -100, 100);}void la_PanelBackgroundInit(laPanel *p, laBoxedTheme *bt){    glClearColor(LA_COLOR4(laThemeColor(bt,LA_BT_NORMAL)));    tnsClearAll();}void la_PanelDrawDescendBorder(laPanel* Panel, laBoxedTheme* bt, int Width, real Alpha);void la_PanelDrawToWindow(laPanel *p, laWindow *w){    real Color[] = {1, 1, 1, 1};    real L, W, U, H;    tnsUseImmShader(); tnsEnableShaderv(T->immShader);    if(MAIN.EnableColorManagement){        tnsUniformOutputColorSpace(T->immShader,w->OutputColorSpace);        tnsUniformShowColorOverflowStripes(T->immShader,w->OutputShowStripes);        tnsUniformColorComposing(T->immShader,w->UseComposing,w->ComposingGamma,w->ComposingBlackpoint);    }else{        tnsUniformOutputColorSpace(T->immShader,0);        tnsUniformShowColorOverflowStripes(T->immShader,0);        tnsUniformColorComposing(T->immShader,0,0,0);    }    if (p->Mode && (!p->AnimationMode || (p->AnimationMode && p->AnimationRatio > 0.99))){        tnsUseNoTexture();        if (!p->IsMenuPanel){            la_PanelDrawDescendBorder(p, (*p->BT), MAIN.SolidShadowLength, MAIN.FloatingAlpha);        }        tnsFlush();    }    switch (p->AnimationMode){    case 0:        tnsDraw2DTextureDirectly(p->OffScr->pColor[0], p->X, p->Y, p->W, p->H);        if(!(p->SR || p->SB || p->Parent || p->Block || p->IsMenuPanel)){            real* color=laThemeColor(_LA_THEME_PANEL,LA_BT_TEXT); tnsColor4d(LA_COLOR3(color),color[3]*(p->ShowCorner?1:0.8));            int len=LA_RH/(p->ShowCorner?1:2); tnsUseNoTexture(); int px=p->X+p->W,py=p->Y+p->H;            tnsVertex2d(px,py); tnsVertex2d(px-len,py); tnsVertex2d(px,py-len);            tnsPackAs(GL_TRIANGLES);            tnsColor4dv(laThemeColor(_LA_THEME_PANEL,LA_BT_NORMAL)); tnsVertex2d(px-len,py); tnsVertex2d(px,py-len);            tnsLineWidth(2); tnsPackAs(GL_LINES); tnsLineWidth(1);        }        break;    case LA_PANEL_ANIMATION_DROP_DOWN:        tnsVectorMultiSelf4d(Color, p->AnimationRatio);        tnsDraw2DTextureArg(            p->OffScr->pColor[0],            p->X, p->Y, p->W, p->H * p->AnimationRatio,            Color,            0, 0, 1 - p->AnimationRatio, 0);        p->AnimationRatio += (1 - p->AnimationRatio) * MAIN.PanelAnimationSpeed * MAIN.LastFrameTime * 60;        if (p->AnimationRatio > 0.99) p->AnimationMode = 0; laRefreshWindow();        break;    case LA_PANEL_ANIMATION_EXPAND:        L = tnsLinearItp(p->X, p->X + p->W, 0.3);        U = tnsLinearItp(p->Y, p->Y + p->H, 0.3);        W = tnsLinearItp(0, p->W, 0.4);        H = tnsLinearItp(0, p->H, 0.4);        tnsVectorMultiSelf4d(Color, p->AnimationRatio);        tnsDraw2DTextureArg(            p->OffScr->pColor[0],            tnsLinearItp(L, p->X, p->AnimationRatio), tnsLinearItp(U, p->Y, p->AnimationRatio),            tnsLinearItp(W, p->W, p->AnimationRatio), tnsLinearItp(H, p->H, p->AnimationRatio),            Color,            0, 0, 0, 0);        p->AnimationRatio += (1 - p->AnimationRatio) * MAIN.PanelAnimationSpeed * MAIN.LastFrameTime * 60;        if (p->AnimationRatio > 0.99) p->AnimationMode = 0; laRefreshWindow();        break;    case LA_PANEL_ANIMATION_DISSOVE:        L = tnsLinearItp(p->X, p->X + p->W, -0.2);        U = tnsLinearItp(p->Y, p->Y + p->H, -0.2);        W = tnsLinearItp(0, p->W, 1.4);        H = tnsLinearItp(0, p->H, 1.4);        tnsVectorMultiSelf4d(Color, (p->AnimationRatio));        if (p->OffScr) tnsDraw2DTextureArg(                p->OffScr->pColor[0],                tnsLinearItp(L, p->X, p->AnimationRatio), tnsLinearItp(U, p->Y, p->AnimationRatio),                tnsLinearItp(W, p->W, p->AnimationRatio), tnsLinearItp(H, p->H, p->AnimationRatio),                Color,                0, 0, 0, 0);        p->AnimationRatio -= (p->AnimationRatio) * MAIN.PanelAnimationSpeed * MAIN.LastFrameTime * 60;        if (p->AnimationRatio < 0.01) p->AnimationMode = 0; laRefreshWindow();        break;    case LA_PANEL_ANIMATION_COLLAPSE:        L = tnsLinearItp(p->X, p->X + p->W, 0.3);        U = tnsLinearItp(p->Y, p->Y + p->H, 0.3);        W = tnsLinearItp(0, p->W, 0.4);        H = tnsLinearItp(0, p->H, 0.4);        tnsVectorMultiSelf4d(Color, p->AnimationRatio);        if (p->OffScr) tnsDraw2DTextureArg(                p->OffScr->pColor[0],                tnsLinearItp(L, p->X, p->AnimationRatio), tnsLinearItp(U, p->Y, p->AnimationRatio),                tnsLinearItp(W, p->W, p->AnimationRatio), tnsLinearItp(H, p->H, p->AnimationRatio),                Color,                0, 0, 0, 0);        p->AnimationRatio -= p->AnimationRatio * MAIN.PanelAnimationSpeed * MAIN.LastFrameTime * 60;        if (p->AnimationRatio < 0.01) p->AnimationMode = 0; laRefreshWindow();        break;    case LA_PANEL_ANIMATION_MINIMIZE:        L = tnsLinearItp(0, p->X, 0.3);        U = tnsLinearItp(w->H, p->Y + p->H, 0.3);        W = tnsLinearItp(0, p->W, 0.4);        H = tnsLinearItp(0, p->H, 0.4);        tnsVectorMultiSelf4d(Color, p->AnimationRatio);        tnsDraw2DTextureArg(            p->OffScr->pColor[0],            tnsLinearItp(L, p->X, p->AnimationRatio), tnsLinearItp(U, p->Y, p->AnimationRatio),            tnsLinearItp(W, p->W, p->AnimationRatio), tnsLinearItp(H, p->H, p->AnimationRatio),            Color,            0, 0, 0, 0);        p->AnimationRatio -= p->AnimationRatio * MAIN.PanelAnimationSpeed * MAIN.LastFrameTime * 60;        if (p->AnimationRatio < 0.01) p->AnimationMode = 0; laRefreshWindow();        break;    }    tnsFlush();    tnsUniformOutputColorSpace(T->immShader,0);    tnsUniformShowColorOverflowStripes(T->immShader,0);    tnsUniformColorComposing(T->immShader,0,0,0);}void la_PanelDrawToOffsceen(laPanel *p, laUiList *uil){    if (p->OffScr){ tnsEnsureOffscreenStatus(p->OffScr, p->W,p->H); }    else{        int GLFormat=(p->PanelTemplate&&p->PanelTemplate->DefaultGLFormat)?p->PanelTemplate->DefaultGLFormat:GL_RGBA8;        p->OffScr = tnsCreate2DOffscreen(GLFormat, p->W, p->H, MAIN.PanelMultisample, 0,0);    }    tnsDrawToOffscreen(p->OffScr, 1, 0);}void la_PanelRefreshDetachedProp(laPanel *panel){    laProp *p;    for (p = panel->PropLinkContainer->Props.pFirst; p; p = p->Item.pNext){        la_StepPropPack(&p->DetachedPP);        la_UsePropPack(&p->DetachedPP, 0);        //if (p->DetachedPP.LastPs && p->DetachedPP.LastPs->p->Container ? p->DetachedPP.LastPs->p->Container->Hyper : 0){        //    laUseDataBlock(        //        p->DetachedPP.LastPs->UseInstance,        //        p->DetachedPP.LastPs->p,        //        MAIN.PropMatcherContextP->FrameDistinguish,        //        MAIN.PropMatcherContextP,        //        la_PropPanelUserRemover, 0);        //}    }}void la_PanelDrawDescendBorder(laPanel *Panel, laBoxedTheme *bt, int Width, real Alpha){    real* color=laThemeColor(bt,LA_BT_BORDER);    tnsColor4d(0,0,0,Alpha);    tnsVertex2d(Panel->X + Width, Panel->Y + Panel->H);    tnsVertex2d(Panel->X + Width, Panel->Y + Panel->H + Width);    tnsVertex2d(Panel->X + Panel->W, Panel->Y + Panel->H);    tnsVertex2d(Panel->X + Panel->W + Width, Panel->Y + Panel->H + Width);    tnsVertex2d(Panel->X + Panel->W, Panel->Y + Width);    tnsVertex2d(Panel->X + Panel->W + Width, Panel->Y + Width);    tnsPackAs(GL_TRIANGLE_STRIP);    tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));    tnsVertex2d(Panel->X-1, Panel->Y-1);    tnsVertex2d(Panel->X-1, Panel->Y + Panel->H+1);    tnsVertex2d(Panel->X+1 + Panel->W, Panel->Y + Panel->H+1);    tnsVertex2d(Panel->X+1 + Panel->W, Panel->Y-1);    tnsLineWidth(2.0); tnsPackAs(GL_LINE_LOOP); tnsLineWidth(1.0);}int la_AnimateUiListRecursive(laUiList *uil);void la_PanelDefDraw(laWindow *w, laPanel *p, laBoxedTheme *bt){    int DrawState_ = 0;    laUiListDraw uild = {0};    if (p->Show){        la_SetPropMathcerContext(p);        MAIN.CurrentPanel = p;        //if(p->Refresh&(LA_TAG_REDRAW|LA_TAG_RECALC)){        //    printf("Draw %0xld (%s)\n", p, p->Title?p->Title->Ptr:0);        //}        if (p->Refresh & LA_TAG_RECALC){            laRecalcPanelImmediate(p);        }        if (!p->MenuRefer){            if(!p->OffScr){ la_PanelDrawToOffsceen(p,&p->UI); p->Refresh|=LA_TAG_REDRAW; laRefreshWindow(); }            if (p->Refresh || !p->OffScr){                la_PanelDrawToOffsceen(p, &p->UI);                la_SetupUiListLimitMatrix(&uild, 0, p->W, 0, p->H, p->H);                la_PanelBackgroundInit(p, bt);                int extrap=(p->Mode && (!p->IsMenuPanel))?p->TitleBar.B:0;                la_DrawUiListScrollerV(&p->UI, p->UI.PanY, p->UI.B-p->UI.U, p->H-bt->BM-bt->TM-extrap, p->W);                tnsFlush();                if(((p->UI.B>p->H) && (!p->UI.ScrollerShownV))||                    ((p->UI.B<=p->H) && p->UI.ScrollerShownV)){                    p->UI.ScrollerShownV=!p->UI.ScrollerShownV;                    DrawState_++;                }                if(p->UI.PanY && p->UI.B-p->UI.PanY<p->H-bt->BM ){                    p->UI.PanY = (p->UI.B-p->H/*-bt->BM-bt->TM*/-p->TitleBar.B);                    if(p->UI.PanY<0){p->UI.PanY=0;}                    DrawState_++;                }                if(p->Refresh&LA_TAG_RECALC_SCROLLER) DrawState_++;                if (!la_AnimateUiListRecursive(&p->TitleBar)) p->Refresh = 0;                else { p->Refresh = LA_TAG_ANIMATION; laRefreshWindow(); }                if (!la_AnimateUiListRecursive(&p->UI)){ p->Refresh = p->Refresh; if(p->Refresh){ laRefreshWindow(); } }                else { p->Refresh = LA_TAG_ANIMATION; laRefreshWindow(); }                DrawState_ += la_DrawUiListRecursive(&uild, &p->TitleBar, 0, p->W, 0, p->H, 10000, -1, 0, 0, 0);                if(p!=w->MaximizedUiPanel){                    DrawState_ += la_DrawUiListRecursive(&uild, &p->UI, 0, p->W, 0, p->H, 10000, -1, 0, 0, 0);                }else{                    tnsViewportWithScissor(0,0,p->W,p->H); tnsOrtho(0,p->W,p->H,0,-100,100);                    tnsDrawStringAutoM("Canvas is maximized",0,laThemeColor(bt,LA_BT_TEXT),                        bt->LM,p->W-bt->RM,(p->H - p->TitleBar.B)/2+LA_RH2,LA_TEXT_ALIGN_CENTER|LA_TEXT_LINE_WRAP);                    tnsFlush();                }                if (DrawState_){ p->Refresh = LA_TAG_RECALC; laRefreshWindow(); }            }        }else{            if (p->Refresh || !p->OffScr){                la_PanelDrawToOffsceen(p, p->MenuRefer);                la_SetupUiListLimitMatrix(&uild, 0, p->W, 0, p->H, p->H);                la_PanelBackgroundInit(p, bt);                la_DrawUiListScrollerV(p->MenuRefer, p->MenuRefer->PanY,                    p->MenuRefer->B-p->MenuRefer->U-bt->TM-bt->BM, p->H-bt->TM-bt->BM*2, p->W);                tnsFlush();                if(((p->MenuRefer->TB>p->H-bt->BP) && (!p->MenuRefer->ScrollerShownV))||                    ((p->MenuRefer->TB<=p->H-bt->BP) && p->MenuRefer->ScrollerShownV)){                    p->MenuRefer->ScrollerShownV=!p->MenuRefer->ScrollerShownV;                    DrawState_++;                }                if(p->UI.PanY && p->MenuRefer->B-p->MenuRefer->PanY<p->H-bt->BM){                    p->MenuRefer->PanY = (p->MenuRefer->B-p->H-bt->BM);                    if(p->MenuRefer->PanY<0){p->MenuRefer->PanY=0;}                    DrawState_++;                }                if(p->Refresh&LA_TAG_RECALC_SCROLLER) DrawState_++;                if (!la_AnimateUiListRecursive(p->MenuRefer)) p->Refresh = 0;                else { p->Refresh = LA_TAG_ANIMATION; laRefreshWindow(); }                DrawState_ += la_DrawUiListRecursive(&uild, p->MenuRefer, 0, p->W, 0, p->H, 10000, -1, 0, 0, 0);                if (DrawState_){ p->Refresh = LA_TAG_RECALC; laRefreshWindow(); }            }        }        tnsDrawToScreen();        tnsViewportWithScissor(0, 0, w->CW, w->CH);        tnsOrtho(0, w->CW, w->CH, 0, -100, 100);        la_PanelDrawToWindow(p, w);    }elif (p->AnimationMode){        la_PanelDrawToWindow(p, w);    }}void la_AttachedPanelDefDraw(laWindow* w, laPanel* p, laBoxedTheme* bt){    if(!p->Show && p!=w->MaximizedUiPanel) return;    if (p->SubPanels.pLast && (p->LaterDestroy ? !p->AnimationMode : 1)){        laPanel *pi, *PrevPI;        for (pi = p->SubPanels.pLast; pi; pi = PrevPI){            PrevPI = pi->Item.pPrev;            if (pi->AnimationMode && pi->LaterDestroy){                lstRemoveItem(&p->SubPanels, pi);                lstAppendItem(&MAIN.CurrentWindow->FadingPanels, pi);                continue;            }            la_PanelDefDraw(w, pi, _LA_THEME_FLOATING_PANEL);            la_AttachedPanelDefDraw(w,pi,bt);        }    }}void la_BlockDrawDropLocations(laBlock *b, int CH, real *BorderColor4dV, real *FillColor4dv){    real PanelSquare[] = {        b->X + 2, CH - (b->Y + 2 + LA_RH),        b->X + 2, CH - (b->Y + b->H - 4),        b->X + b->W - 4, CH - (b->Y + b->H - 4),        b->X + b->W - 4, CH - (b->Y + 2 + LA_RH)};    real Center[] = {        tnsLinearItp(PanelSquare[0], PanelSquare[4], 0.5), tnsLinearItp(PanelSquare[1], PanelSquare[5], 0.5)};    real DraggingPlot[] = {        tnsLinearItp(PanelSquare[0], Center[0], 0.5),        tnsLinearItp(PanelSquare[1], Center[1], 0.5),        PanelSquare[0],        PanelSquare[1],        tnsLinearItp(PanelSquare[2], Center[0], 0.5),        tnsLinearItp(PanelSquare[3], Center[1], 0.5),        PanelSquare[2],        PanelSquare[3],        tnsLinearItp(PanelSquare[4], Center[0], 0.5),        tnsLinearItp(PanelSquare[5], Center[1], 0.5),        PanelSquare[4],        PanelSquare[5],        tnsLinearItp(PanelSquare[6], Center[0], 0.5),        tnsLinearItp(PanelSquare[7], Center[1], 0.5),        PanelSquare[6],        PanelSquare[7],    };    real Square[] = {        tnsLinearItp(PanelSquare[0], Center[0], 0.5),        tnsLinearItp(PanelSquare[1], Center[1], 0.5),        tnsLinearItp(PanelSquare[2], Center[0], 0.5),        tnsLinearItp(PanelSquare[3], Center[1], 0.5),        tnsLinearItp(PanelSquare[4], Center[0], 0.5),        tnsLinearItp(PanelSquare[5], Center[1], 0.5),        tnsLinearItp(PanelSquare[6], Center[0], 0.5),        tnsLinearItp(PanelSquare[7], Center[1], 0.5),    };    real PlotColor[] = {LA_COLOR3(BorderColor4dV), 0.8,        LA_COLOR3(BorderColor4dV), 0,        LA_COLOR3(BorderColor4dV), 0.8,        LA_COLOR3(BorderColor4dV), 0,        LA_COLOR3(BorderColor4dV), 0.8,        LA_COLOR3(BorderColor4dV), 0,        LA_COLOR3(BorderColor4dV), 0.8,        LA_COLOR3(BorderColor4dV), 0,    };    real FillColor[] = {LA_COLOR3(FillColor4dv), 0.8,        LA_COLOR3(FillColor4dv), 0,        LA_COLOR3(FillColor4dv), 0.8,        LA_COLOR3(FillColor4dv), 0,        LA_COLOR3(FillColor4dv), 0.8,        LA_COLOR3(FillColor4dv), 0,        LA_COLOR3(FillColor4dv), 0.8,        LA_COLOR3(FillColor4dv), 0,    };    tnsUseNoTexture();    if (MAIN.CurrentWindow->CurrentLayout->DropToBlock == b){        int Index[4];        tnsVertexArray2d(DraggingPlot, 8);        tnsColorArray4d(FillColor, 8);        switch (MAIN.CurrentWindow->CurrentLayout->DropLocation){        case 0:            Index[0] = 0; Index[1] = 2; Index[2] = 4; Index[3] = 6;            break;        case LA_BLOCK_DROP_LOCATION_L:            Index[0] = 0; Index[1] = 1; Index[2] = 3; Index[3] = 2;            break;        case LA_BLOCK_DROP_LOCATION_R:            Index[0] = 4; Index[1] = 5; Index[2] = 7; Index[3] = 6;            break;        case LA_BLOCK_DROP_LOCATION_U:            Index[0] = 0; Index[1] = 1; Index[2] = 7; Index[3] = 6;            break;        case LA_BLOCK_DROP_LOCATION_B:            Index[0] = 4; Index[1] = 5; Index[2] = 3; Index[3] = 2;            break;        }        //glDisable(GL_CULL_FACE);        tnsIndexArray(Index, 4);        tnsPackAs(GL_TRIANGLE_FAN);        //tnsFlush();    }    tnsVertexArray2d(DraggingPlot, 8);    tnsColorArray4d(PlotColor, 8);    tnsPackAs(GL_LINES);    tnsVertexArray2d(Square, 4);    tnsColor4dv(BorderColor4dV);    tnsPackAs(GL_LINE_LOOP);    glLineWidth(LA_SEAM_W);    tnsFlush();    glLineWidth(1);}void la_BlockDefDrawSelf(laBlock *b, int CH){    laBoxedTheme *bt = _LA_THEME_TAB;    laPanel *p;    real v[] = {        b->X, CH - b->Y,        b->X + LA_SEAM_W, CH - b->Y ,        b->X, CH - (b->Y + b->H),        b->X + LA_SEAM_W, CH - (b->Y + b->H - LA_SEAM_W),        b->X + b->W, CH - (b->Y + b->H),        b->X + b->W - LA_SEAM_W, CH - (b->Y + b->H - LA_SEAM_W),        b->X + b->W, CH - b->Y,        b->X + b->W - LA_SEAM_W, CH - b->Y};    real tv[8];    real ratio = 1.0001f;    int tw = 0;    int L = LA_RH+LA_SEAM_W;    tnsUseImmShader(); tnsEnableShaderv(T->immShader);    if(MAIN.EnableColorManagement){        tnsUniformOutputColorSpace(T->immShader,MAIN.CurrentWindow->OutputColorSpace);        tnsUniformColorComposing(T->immShader,MAIN.CurrentWindow->UseComposing,MAIN.CurrentWindow->ComposingGamma,MAIN.CurrentWindow->ComposingBlackpoint);    }else{        tnsUniformOutputColorSpace(T->immShader,0);        tnsUniformColorComposing(T->immShader,0,0,0);    }    for (p = b->Panels.pFirst; p; p = p->Item.pNext){        tw += p->TitleWidth + LA_SEAM_W*2;    }    if (tw > b->W - LA_SEAM_W*2 - LA_RH) ratio = (real)(b->W - LA_SEAM_W*2 - LA_RH) / (real)tw;    tnsUseNoTexture();    tnsColor4dv(laThemeColor(bt,LA_BT_ACTIVE));    tnsVertexArray2d(v, 8);    tnsPackAs(GL_TRIANGLE_STRIP);    int TitleGap=b->Folded?0:LA_RH;    tnsMakeQuad2d(tv, b->X, (CH - b->Y),                    b->X + b->W, (CH - b->Y),                    b->X + b->W, (CH - b->Y - TitleGap),                    b->X, (CH - b->Y - TitleGap));    tnsColor4dv(laThemeColor(bt,LA_BT_ACTIVE));    tnsVertexArray2d(tv, 4);    tnsPackAs(GL_TRIANGLE_FAN);    tnsMakeQuad2d(tv,b->X + LA_SEAM_W, (CH - b->Y - TitleGap),                    b->X + b->W - LA_SEAM_W, (CH - b->Y - TitleGap),                    b->X + b->W - LA_SEAM_W, (CH - b->Y - TitleGap - LA_SEAM_W),                    b->X + LA_SEAM_W, (CH - b->Y - TitleGap- LA_SEAM_W));    tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));    tnsVertexArray2d(tv, 4);    tnsPackAs(GL_TRIANGLE_FAN);    if(b->Folded){        real Color[4]; tnsVectorCopy4d(laThemeColor(bt,LA_BT_BORDER), Color); Color[3]*=b->OnButton==2?1:(b->OnButton==1?0.3:0);        tnsDrawStringAuto("⯆",Color, b->X+LA_SEAM_W,b->X+LA_SEAM_W+LA_RH, CH-b->Y, LA_TEXT_REVERT_Y|LA_TEXT_ALIGN_CENTER);        tnsDrawStringAuto("⮼",Color, b->X+LA_SEAM_W+LA_RH,b->X+LA_SEAM_W+LA_2RH, CH-b->Y, LA_TEXT_REVERT_Y|LA_TEXT_ALIGN_CENTER);        tnsFlush(); return;     }    int LT=0,RT=0;    for (p = b->Panels.pFirst; p; p = p->Item.pNext){        RT = LT + p->TitleWidth + LA_SEAM_W*2;        tnsMakeQuad2d(tv,b->X + L+LT * ratio, (CH - b->Y),                         b->X + L+RT * ratio, (CH - b->Y),                         b->X + L+RT * ratio, (CH - b->Y - LA_RH),                         b->X + L+LT * ratio, (CH - b->Y - LA_RH));        if (p == b->CurrentPanel){            tnsUseNoTexture();            tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));            tnsVertexArray2d(tv, 4);            tnsPackAs(GL_TRIANGLE_FAN);            tnsDrawStringAuto(transLate(p->Title->Ptr), laThemeColor(bt,LA_BT_TEXT_ACTIVE), b->X + L +LT* ratio + LA_SEAM_W, b->X + L +RT* ratio, CH - b->Y, LA_TEXT_REVERT_Y);        }else{            tnsDrawStringAuto(transLate(p->Title->Ptr), laThemeColor(bt,LA_BT_TEXT), b->X + L +LT* ratio + LA_SEAM_W, b->X + L +RT* ratio, CH - b->Y, LA_TEXT_REVERT_Y);        }        LT =RT;    }    tnsDrawStringAuto("🔻",laThemeColor(bt,LA_BT_BORDER), b->X+LA_SEAM_W,b->X+b->W, CH-b->Y, LA_TEXT_REVERT_Y);    tnsFlush();    tnsUniformOutputColorSpace(T->immShader,0);    tnsUniformColorComposing(T->immShader,0,0,0);}void la_BlockDefDrawSelfEmpty(laBlock *b, int CH){    laBoxedTheme *bt = _LA_THEME_PANEL;    real tv[8];    tnsUseImmShader(); tnsEnableShaderv(T->immShader);    if(MAIN.EnableColorManagement){        tnsUniformOutputColorSpace(T->immShader,MAIN.CurrentWindow->OutputColorSpace);        tnsUniformColorComposing(T->immShader,MAIN.CurrentWindow->UseComposing,MAIN.CurrentWindow->ComposingGamma,MAIN.CurrentWindow->ComposingBlackpoint);    }else{        tnsUniformOutputColorSpace(T->immShader,0);        tnsUniformColorComposing(T->immShader,0,0,0);    }        tnsUseNoTexture();    tnsMakeQuad2d(tv, b->X, (CH - b->Y),                      b->X + b->W, (CH - b->Y),                      b->X + b->W, (CH - b->Y-b->H),                      b->X, (CH - b->Y-b->H));    tnsVertexArray2d(tv, 4);    tnsColor4dv(laThemeColor(bt,LA_BT_NORMAL));    tnsPackAs(GL_TRIANGLE_FAN);    tnsDrawStringAuto(transLate("Dock some panels here."), laThemeColor(bt,LA_BT_TEXT), b->X+LA_SEAM_W,b->X+b->W-LA_SEAM_W, CH-b->Y-b->H/2+LA_RH2,        LA_TEXT_ALIGN_CENTER|LA_TEXT_REVERT_Y|LA_TEXT_USE_NEWLINE|LA_TEXT_LINE_WRAP);    tnsFlush();    tnsUniformOutputColorSpace(T->immShader,0);    tnsUniformColorComposing(T->immShader,0,0,0);}void la_BlockDefDrawRecursive(laWindow *w, laBoxedTheme *bt, laBlock *b){    if (b->B1){        la_BlockDefDrawRecursive(w, bt, b->B1);        la_BlockDefDrawRecursive(w, bt, b->B2);    }elif (b->CurrentPanel /*&& b->CurrentPanel->Refresh*/){        if (!b->CurrentPanel->BT) b->CurrentPanel->BT = &_LA_THEME_PANEL;        la_PanelDefDraw(w, b->CurrentPanel, *b->CurrentPanel->BT);        tnsViewportWithScissor(0, 0, w->CW, w->CH);        tnsOrtho(0, w->CW, 0, w->CH, -100, 100);        la_BlockDefDrawSelf(b, w->CH);    }else{        tnsViewportWithScissor(0, 0, w->CW, w->CH);        tnsOrtho(0, w->CW, 0, w->CH, -100, 100);        la_BlockDefDrawSelfEmpty(b, w->CH);    }    if(b==MAIN.CurrentWindow->CurrentLayout->MovingBlock){        tnsUseNoTexture();        int at; real tv[8];        if (b->Vertical){            at = b->H * b->SplitRatio + b->Y;            tnsMakeQuad2d(tv,b->X, (w->CH - at + LA_SEAM_W),                            b->X + b->W, (w->CH - at + LA_SEAM_W),                            b->X + b->W, (w->CH - at - LA_SEAM_W),                            b->X, (w->CH - at - LA_SEAM_W));        }else{            at = b->X + b->W * b->SplitRatio;            tnsMakeQuad2d(tv,at+ LA_SEAM_W, (w->CH - b->Y),                            at- LA_SEAM_W, (w->CH - b->Y),                            at- LA_SEAM_W, (w->CH - b->Y - b->H),                            at+ LA_SEAM_W, (w->CH - b->Y - b->H));        }        tnsColor4dv(laThemeColor(_LA_THEME_TAB,LA_BT_BORDER));        tnsVertexArray2d(tv, 4);        tnsPackAs(GL_TRIANGLE_FAN);    }    //la_SetPanelMatrixDrawWindow(b->CurrentPanel, *b->CurrentPanel->BT);    tnsFlush();}void la_BlockDefDrawAttachedRecursive(laWindow *w, laBoxedTheme *bt, laBlock *b){    if (b->B1){        la_BlockDefDrawAttachedRecursive(w, bt, b->B1);        la_BlockDefDrawAttachedRecursive(w, bt, b->B2);    }elif (b->CurrentPanel /*&& b->CurrentPanel->Refresh*/){        la_AttachedPanelDefDraw(w,b->CurrentPanel,*b->CurrentPanel->BT);    }    tnsFlush();}void la_ClearBlockFramebuffersRecursive(laBlock* b, int AlsoClearCurrent){    if(b->B1)la_ClearBlockFramebuffersRecursive(b->B1,AlsoClearCurrent);    if(b->B2)la_ClearBlockFramebuffersRecursive(b->B2,AlsoClearCurrent);    for(laPanel* p=b->Panels.pFirst;p;p=p->Item.pNext){        if(!AlsoClearCurrent && p==b->CurrentPanel) continue;        if(p->OffScr){            tnsDelete2DOffscreen(p->OffScr); p->OffScr=0;        }    }}void la_ClearUnusedFramebuffers(laWindow* w){    for(laLayout* l = w->Layouts.pFirst;l;l=l->Item.pNext){        la_ClearBlockFramebuffersRecursive(l->FirstBlock, l!=w->CurrentLayout);    }    for(laPanel* p=w->Panels.pFirst;p;p=p->Item.pNext){        if(p->Show || p->AnimationMode) continue;        if(p->OffScr){            tnsDelete2DOffscreen(p->OffScr); p->OffScr=0;        }    }}void laDeferredDestroyPanel(laPanel* p, int immediate);void la_WindowDefDraw(laWindow *w, laBoxedTheme *bt){    laPanel *p, *NextP;    laLayout *l = w->CurrentLayout;    la_ClearUnusedFramebuffers(w);    tnsDrawToScreen();    tnsViewportWithScissor(0, 0, w->CW, w->CH);    glClearColor(0.2, 0.2, 0.3, 1.0);    tnsClearAll();    tnsUseNoTexture();    if (l->Draw) l->Draw(w, l);    tnsResetModelMatrix();tnsResetProjectionMatrix();tnsResetViewMatrix();    glEnable(GL_BLEND);    //lBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE_MINUS_SRC_ALPHA);    laUiItem* ui;    if((ui=w->MaximizedUi) && w->MaximizedUiPanel && ui->Type->Draw && ui->CanvasTemplate->SecondDraw){        MAIN.CurrentPanel=w->MaximizedUiPanel; laPanel* p=w->MaximizedUiPanel; int DrawState_=0;        la_SetPropMathcerContext(p);        if(p->Refresh){            if (!p->BT) p->BT = &_LA_THEME_PANEL;            tnsUseShader(T->immShader);tnsEnableShaderv(T->immShader);            if(MAIN.EnableColorManagement){                tnsUniformOutputColorSpace(T->immShader,w->OutputColorSpace);                tnsUniformColorComposing(T->immShader,w->UseComposing,w->ComposingGamma,w->ComposingBlackpoint);            }else{                tnsUniformOutputColorSpace(T->immShader,0);                tnsUniformColorComposing(T->immShader,0,0,0);            }            if(p->Refresh&LA_TAG_RECALC){                laRecalcPanelImmediate(p);            }            ui->Type->Draw(ui, LA_RH); tnsFlush();            if (!la_AnimateUiListRecursive(&p->UI)) p->Refresh = 0;            else { p->Refresh|=LA_TAG_ANIMATION; laRefreshWindow(); }        }        tnsDrawToScreen();        tnsResetViewMatrix();        tnsViewportWithScissor(0, 0, w->CW, w->CH);        tnsOrtho(0, w->CW, w->CH, 0, -100, 100);        ui->CanvasTemplate->SecondDraw(ui, LA_RH);        tnsFlush();        if(!(ui->Flags&LA_UI_FLAGS_NO_OVERLAY)){            laUiListDraw uild = {0}; for (laUiList* sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){                tnsFlush();                DrawState_+=la_DrawUiListRecursive(&uild, sub, ui->L, ui->R, ui->U, ui->B, 10000, 0, 0, 0, 0);            }        }        if (DrawState_){ p->Refresh = LA_TAG_RECALC; laRefreshWindow(); }        la_AttachedPanelDefDraw(w,p,*p->BT);    }else{        laBlock* RootBlock= w->MaximizedBlock?w->MaximizedBlock:l->FirstBlock;        la_BlockDefDrawRecursive(w, bt, RootBlock);        la_BlockDefDrawAttachedRecursive(w,bt, RootBlock);    }    for (p = w->Panels.pLast; p; p = NextP){        NextP = p->Item.pPrev;        if (!p->BT) p->BT = &_LA_THEME_FLOATING_PANEL;        if (p->AnimationMode && p->LaterDestroy){            lstRemoveItem(&w->Panels, p);            lstAppendItem(&MAIN.CurrentWindow->FadingPanels, p);            continue;        }        la_PanelDefDraw(w, p, *p->BT);    }    for(laPanel* p=w->Panels.pFirst;p;p=p->Item.pNext){        la_AttachedPanelDefDraw(w,p,*p->BT);    }    if (MAIN.CurrentWindow->CurrentLayout->DropToBlock){        laBoxedTheme* ubt=_LA_THEME_TAB;tnsUseNoTexture();        tnsViewportWithScissor(0, 0, w->CW, w->CH); tnsOrtho(0, w->CW, 0, w->CH, -100, 100);        la_BlockDrawDropLocations(MAIN.CurrentWindow->CurrentLayout->DropToBlock,            MAIN.CurrentWindow->CH, laThemeColor(ubt,LA_BT_ACTIVE), laThemeColor(ubt,LA_BT_BORDER));        tnsFlush();    }    for (p = w->FadingPanels.pLast; p; p = NextP){        NextP = p->Item.pPrev;        if (!p->AnimationMode){            lstRemoveItem(&w->FadingPanels, p);            p->AnimationMode = LA_PANEL_ANIMATION_DESTROY; laRefreshWindow();            laDeferredDestroyPanel(p, 0);        }else            la_PanelDrawToWindow(p, w);    }}int laStartWindow(laWindow *w){#ifdef __linux__    XMapWindow(MAIN.dpy,w->win);    tnsContextMakeWindowCurrent(w);#endif#ifdef _WIN32    ShowWindow(w->win, SW_SHOWNORMAL);#endif    MAIN.CurrentWindow = w;    if(!w->CurrentLayout){        if(!w->Layouts.pFirst){laDesignLayout(w, "Empty Layout");}        memAssignRef(w, &w->CurrentLayout, w->Layouts.pFirst);    }    laRedrawCurrentWindow();    laInvokeUi(0, "LA_window_operator", 0, w, 0, 0);    w->Shown = 1;}void la_AssignWindowPP(laWindow* w){    w->PP.EndInstance = w;    w->PP.LastPs = &w->FakePS;    w->PP.LastPs->p = _LA_PROP_WINDOW;    w->PP.LastPs->UseInstance = w;    w->PP.LastPs->Type = U'.';}laWindow *laDesignWindow(int X, int Y, int W, int H){    laWindow *n = memAcquire(sizeof(laWindow));    strSafeSet(&n->Title, "Empty SYSWINDOW");    n->X = X; n->Y = Y; n->W = W; n->H = H;    la_CreateSystemWindow(n, MAIN.Windows.pFirst!=0);    lstAppendItem(&MAIN.Windows, n);    MAIN.CurrentWindow = n;    la_AssignWindowPP(n);    laui_DefaultMenuBar(n);    return n;}void laSetWindowCursor(int id){    MAIN.CurrentCursor = id;#ifdef __linux__    Cursor c = XcursorLibraryLoadCursor(MAIN.dpy, la_ConvertCursorID(id));    XDefineCursor(MAIN.dpy, MAIN.CurrentWindow->win, c);#endif#ifdef _WIN32    SetCursor(la_ConvertCursorID(id));#endif};void la_AssignBlockPP(laBlock* b){    b->PP.EndInstance = b;    b->PP.LastPs = &b->FakePS;    b->PP.LastPs->p = _LA_PROP_BLOCK;    b->PP.LastPs->UseInstance = b;    b->PP.LastPs->Type = U'.';}void laDestroyLayout(laWindow *w, laLayout* l){    if((!l->Item.pPrev) && (!l->Item.pNext)) return;    laDestroyBlocksRecursive(l->FirstBlock);    strSafeDestroy(&l->ID);    if(w->CurrentLayout==l){ memAssignRef(w, &w->CurrentLayout, l->Item.pPrev?l->Item.pPrev:l->Item.pNext); }    lstRemoveItem(&w->Layouts,l); memFree(l);}laLayout *laDesignLayout(laWindow *w, char *Title){    laLayout *l = memAcquire(sizeof(laLayout));    l->FirstBlock = memAcquire(sizeof(laBlock));    la_AssignBlockPP(l->FirstBlock);    lstAppendItem(&w->Layouts, l);    strSafeSet(&l->ID, Title);    memAssignRef(w, &w->CurrentLayout, l);    laRenameWindow(w, Title);    return l;}void laFoldBlockTitle(laBlock* b){ if(b->B1) return; b->Folded=1; la_RecalcBlockRecursive(b,b->X,b->Y,b->W,b->H); }void laUnfoldBlockTitle(laBlock* b){ if(b->B1) return; b->Folded=0; b->OnButton=0; la_RecalcBlockRecursive(b,b->X,b->Y,b->W,b->H); }void laMaximizeBlock(laBlock* b){ if(b->B1) return; laWindow* w=MAIN.CurrentWindow;    if(w->MaximizedBlock==b){laRestoreToLayout(); return;} w->MaximizedBlock=b; la_UpdateUiPlacement(w);    laNotifyUsers("la.windows.maximized_block"); }void laRestoreToLayout(){ laWindow* w=MAIN.CurrentWindow; if(!w->MaximizedBlock) return;  w->MaximizedBlock=0; la_UpdateUiPlacement(w);    laNotifyUsers("la.windows.maximized_block"); }void laMaximizeCanvasUI(laUiItem* ui, laPanel* UiParentPanel){    laRestoreCanvasUI();    if(!ui->Type||(!(ui->Type->Tag&LA_UI_TAG_IS_OFFSCREEN))||!UiParentPanel) return;    la_StopUiOperatorService(UiParentPanel); la_StopUiOperatorService(ui); laRetriggerOperators();    laWindow* w=MAIN.CurrentWindow; w->MaximizedUi=ui; w->MaximizedUiPanel=UiParentPanel; laRecalcPanel(UiParentPanel);    UiParentPanel->Show=0;    laNotifyUsers("la.windows.maximized_ui"); laHideMenuBar();}void laRestoreCanvasUI(){    laWindow* w=MAIN.CurrentWindow; if(!w->MaximizedUi || !w->MaximizedUiPanel) return;    la_StopUiOperatorService(w->MaximizedUi); laRetriggerOperators(); w->MaximizedUiPanel->Show=1;    laRecalcPanel(w->MaximizedUiPanel); w->MaximizedUi=0; w->MaximizedUiPanel=0; la_UpdateUiPlacement(w);    laNotifyUsers("la.windows.maximized_ui"); laShowMenuBar();}void laHideMenuBar(){ laWindow* w=MAIN.CurrentWindow; if(!w->MaximizedUi || !w->MaximizedUiPanel) return;    for(laPanel* p=MAIN.CurrentWindow->Panels.pFirst;p;p=p->Item.pNext){ if(p->IsMenuPanel){ p->Show=0; laRefreshWindow(); break; } }}void laShowMenuBar(){ for(laPanel* p=MAIN.CurrentWindow->Panels.pFirst;p;p=p->Item.pNext){ if(p->IsMenuPanel){ p->Show=1; laRefreshWindow(); break; } } }void laSplitBlockHorizon(laBlock *b, real Percentage){    laPanel *p;    b->SplitRatio = Percentage;    b->Vertical = 0;    b->B1 = memAcquire(sizeof(laBlock)); la_AssignBlockPP(b->B1); b->B1->Folded=b->Folded;    b->B2 = memAcquire(sizeof(laBlock)); la_AssignBlockPP(b->B2);    for (p = b->Panels.pFirst; p; p = p->Item.pNext){        p->Block = b->B1;    }    b->B1->Panels.pFirst = b->Panels.pFirst;    b->B1->Panels.pLast = b->Panels.pLast;    b->B1->CurrentPanel = b->CurrentPanel;    b->B1->parent = b->B2->parent=b;    b->Panels.pFirst = 0;    b->Panels.pLast = 0;    b->CurrentPanel = 0;    la_RecalcBlockRecursive(b, b->X, b->Y, b->W, b->H);}void laSplitBlockVertical(laBlock *b, real Percentage){    laPanel *p;    b->SplitRatio = Percentage;    b->Vertical = 1;    b->B1 = memAcquire(sizeof(laBlock)); la_AssignBlockPP(b->B1); b->B1->Folded=b->Folded;    b->B2 = memAcquire(sizeof(laBlock)); la_AssignBlockPP(b->B2);    for (p = b->Panels.pFirst; p; p = p->Item.pNext){        p->Block = b->B1;    }    b->B1->Panels.pFirst = b->Panels.pFirst;    b->B1->Panels.pLast = b->Panels.pLast;    b->B1->CurrentPanel = b->CurrentPanel;    b->B1->parent = b->B2->parent=b;    b->Panels.pFirst = 0;    b->Panels.pLast = 0;    b->CurrentPanel = 0;    la_RecalcBlockRecursive(b, b->X, b->Y, b->W, b->H);}void laCombineChildBlocks(laBlock *b){    laPanel *p; if(!b) return;    if (!b->B1->B1 && !b->B2->B1){        lstCombineLists(&b->Panels, &b->B1->Panels);        lstCombineLists(&b->Panels, &b->B2->Panels);        for (p = b->Panels.pFirst; p; p = p->Item.pNext){            p->Block = b;        }        b->CurrentPanel = b->B1->CurrentPanel?b->B1->CurrentPanel:b->B2->CurrentPanel;        memFree(b->B1);        memFree(b->B2);        b->B1 = 0;        b->B2 = 0;        la_RecalcBlockRecursive(b, b->X, b->Y, b->W, b->H);    }elif(!b->B1->B1){        laBlock* b1 = b->B2->B1; laBlock* b2 = b->B2->B2;        b->Vertical = b->B2->Vertical;        for (p = b->B1->Panels.pFirst; p; p = p->Item.pNext){            p->Block = b1;        }        lstCombineLists(&b1->Panels, &b->B1->Panels);        memFree(b->B1); memFree(b->B2);        b->B1 = b1; b->B2 = b2;        b1->parent = b; b2->parent = b;        la_RecalcBlockRecursive(b, b->X, b->Y, b->W, b->H);    }elif(!b->B2->B1){        laBlock* b1 = b->B1->B1;laBlock* b2 = b->B1->B2;        b->Vertical = b->B1->Vertical;        for (p = b->B2->Panels.pFirst; p; p = p->Item.pNext){            p->Block = b1;        }        lstCombineLists(&b1->Panels, &b->B2->Panels);        memFree(b->B1); memFree(b->B2);        b->B1 = b1; b->B2 = b2;        b1->parent = b; b2->parent = b;        la_RecalcBlockRecursive(b, b->X, b->Y, b->W, b->H);    }}laBlock *laBlock1(laBlock *b){    return b->B1;}laBlock *laBlock2(laBlock *b){    return b->B2;}laBlock *laSwapSubBlocks(laBlock *b){    laBlock *tB;    tB = b->B2;    b->B2 = b->B1;    b->B1 = tB;    b->SplitRatio = 1 - b->SplitRatio;    la_RecalcBlockRecursive(b, b->X, b->Y, b->W, b->H);}void laDestroyBlocksRecursive(laBlock *Root){    laPanel *p;    if (Root->B1){        laDestroyBlocksRecursive(Root->B1);        laDestroyBlocksRecursive(Root->B2);    }else{        while (p = lstPopItem(&Root->Panels)){ laDestroySinglePanel(p, 1); }    }    memFree(Root);}laPanel* laTearOffPanel(laBlock* b, laPanel* p_if_set){    if(!b->CurrentPanel ) return 0;    laPanel* p = p_if_set?p_if_set:b->CurrentPanel;    b->CurrentPanel = p->Item.pNext?p->Item.pNext:p->Item.pPrev;    lstRemoveItem(&b->Panels, p);    if(!b->CurrentPanel && b->parent){ b=b->parent; laCombineChildBlocks(b); }    if(!p->TitleBar.UiItems.pFirst){        laui_DefaultPanelTitleBar(&p->TitleBar, &p->PP, &p->PropLinkPP, p->PanelTemplate?p->PanelTemplate->Header:0);    }    p->Mode = LA_PANEL_FLOATING_TOP;    p->TY-=LA_RH; p->TH+=LA_RH;    p->W=p->TW=(p->PanelTemplate?p->PanelTemplate->DefaultW_RH:20)*LA_RH;    p->W=p->TH=(p->PanelTemplate?p->PanelTemplate->DefaultH_RH:20)*LA_RH;    p->Block = 0;    laEnsurePanelInBound(p,&p->UI); laPlacePanelForCreation(p);    laRecalcPanel(p);    la_RecalcBlockRecursive(b, b->X,b->Y,b->W,b->H);    p->BT = &_LA_THEME_FLOATING_PANEL;    lstPushItem(&MAIN.CurrentWindow->Panels, p);    laNotifyUsers("la.windows.panels");    return b->CurrentPanel;}void laDockPanel(laWindow* from, laBlock* b, laPanel* p){    if(!b||!p||p->Mode!=LA_PANEL_FLOATING_TOP||b->B1||b->B2) return;    lstRemoveItem(&from->Panels, p);    la_DestroyUiList(&p->TitleBar, 1, 1, 0);    p->Mode = LA_PANEL_NORMAL;    p->Block=b;    b->CurrentPanel = p;    lstPushItem(&b->Panels, p);    laRecalcPanel(p);    p->BT = &_LA_THEME_PANEL;    la_RecalcBlockRecursive(b, b->X,b->Y,b->W,b->H);    tnsFlush();    laNotifyUsers("la.windows.panels");}void laPopPanel(laPanel *p){    if (p->Mode == LA_PANEL_FLOATING_PASSIVE){        lstRemoveItem(&p->Parent->SubPanels, p);        lstPushItem(&p->Parent->SubPanels, p);    }else if (p->Mode == LA_PANEL_FLOATING_TOP){        lstRemoveItem(&MAIN.CurrentWindow->Panels, p);        lstPushItem(&MAIN.CurrentWindow->Panels, p);        laNotifyUsers("la.windows.panels");    }}void la_EnsurePanelExtras(laPanel *p){    laUiTemplate* uit=p->PanelTemplate;    p->PropLinkContainer = memAcquire(sizeof(laPropContainer));    p->PropLinkFakeProp = memAcquire(sizeof(laSubProp));    p->PropLinkFakeProp->Base.Identifier = "LA_UI_FAKE_PROP_PLACEHOLDER";    p->PropLinkFakeProp->Base.PropertyType = LA_PROP_SUB;    p->PropLinkFakeProp->Base.SubProp = p->PropLinkContainer;    p->PropLinkFakeProp->Base.Offset = 0;    p->PropLinkFakeProp->Base.OffsetIsPointer = 1;    p->PropLinkPP.EndInstance = p;    p->PropLinkPP.LastPs = &p->PropLinkFakePS;    p->PropLinkPP.LastPs->Type = U'.';    p->PropLinkFakePS.p = p->PropLinkFakeProp;}laPanel* la_GivePanelNode(){    laPanel* p; if(p=lstPopItem(&MAIN.WastedPanels)) return p;    return memAcquire(sizeof(laPanel));}void la_ReturnPanelNode(laPanel* p){    memset(p,0,sizeof(laPanel));    lstRemovePointer(&MAIN.DeferredRedrawList,p);    lstAppendItem(&MAIN.WastedPanels, p);}laPanel *la_NewPanel(laUiTemplate* uit, int X, int Y, int W, int H, int MaxW, int MaxH, int MinW, int MinH, int SnapL, int SnapR, int SnapT, int SnapB){    laPanel *p = la_GivePanelNode();    int CW = MAIN.CurrentWindow->CW;    int CH = MAIN.CurrentWindow->CH;    p->PanelTemplate = uit;    if((!W) && uit)W=uit->DefaultW_RH*LA_RH;    if((!H) && uit)H=uit->DefaultH_RH*LA_RH;    if (!MaxW) MaxW = 10000;    if (!MaxH) MaxH = 10000;    if (W > MaxW) W = MaxW;    if (H > MaxH) H = MaxH;    if (W < MinW) W = MinW;    if (H < MinH) H = MinH;    if(uit) { strSafeSet(&p->Title, uit->Title->Ptr); }    p->X = p->TX = (X < 0 ? 0 : X);    p->Y = p->TY = (Y < 0 ? 0 : Y);    p->W = p->TW = (W < 0 ? CW + W - p->X : W);    p->H = p->TH = (H < 0 ? CH + H - p->Y : H);    p->MaxW = MaxW; p->MaxH = MaxH;    p->MinW = MinW; p->MinH = MinH;    p->SL = SnapL; p->ST = SnapT;    p->SR = SnapR; p->SB = SnapB;    if (p->SR) p->X = CW - p->W - p->SR;    if (p->SB) p->Y = CH - p->H - p->SB;    la_EnsurePanelSnapping(p, CW, CH);    p->Show = 1;    p->PP.EndInstance = p;    p->PP.LastPs = &p->FakePS;    p->PP.LastPs->p = _LA_PROP_PANEL;    p->PP.LastPs->UseInstance = p;    p->PP.LastPs->Type = U'.';    la_EnsurePanelExtras(p);    laRecalcPanel(p);    p->FrameDistinguish = 100; //greater than 1 is ok    if(uit&&uit->PropFunc){ uit->PropFunc(p); }    if(uit){uit->Define(&p->UI, &p->PP, &p->PropLinkPP, 0, 0);}    return p;}laPanel *laCreatePanelT(laBlock *b, laUiTemplate* uit){    if(!uit) return 0;    laPanel *p = memAcquireHyper(sizeof(laPanel));    strSafeSet(&p->Title, uit->Title->Ptr);    p->PanelTemplate = uit;    p->Show = 1;    p->PP.EndInstance = p;    p->PP.LastPs = &p->FakePS;    p->PP.LastPs->p = _LA_PROP_PANEL;    p->PP.LastPs->UseInstance = p;    p->PP.LastPs->Type = U'.';    la_EnsurePanelExtras(p);        laRecalcPanel(p);    p->FrameDistinguish = 100; //greater than 1 is ok    p->TitleWidth = tnsStringGetWidth(transLate(p->Title->Ptr), 0, 0);    while (b->B1){ b = b->B1; } lstPushItem(&b->Panels, p);    p->Block = b; b->CurrentPanel = p;    if(uit->PropFunc){ uit->PropFunc(p); }    uit->Define(&p->UI, &p->PP, &p->PropLinkPP, 0, 0);    laNotifyUsers("la.windows.panels");    return p;}laPanel *laCreatePanel(laBlock *b, char *template_id){    laUiTemplate* uit=laFindUiTemplate(template_id);    return laCreatePanelT(b, uit);}laPanel *laCreateTopPanel(laWindow *w, char *template_id, int X, int Y, int W, int H, int MaxW, int MaxH, int MinW, int MinH, int SnapL, int SnapR, int SnapT, int SnapB){    laUiTemplate* uit=0;    if(template_id) uit=laFindUiTemplate(template_id);    laPanel *p = la_NewPanel(uit, X, Y, W, H, MaxW, MaxH, MinW, MinH, SnapL, SnapR, SnapT, SnapB);    p->Mode = LA_PANEL_FLOATING_TOP;    laPlacePanelForCreation(p);    if(uit){        laui_DefaultPanelTitleBar(&p->TitleBar, &p->PP, &p->PropLinkPP, p->PanelTemplate->Header);    }    if (w) lstPushItem(&w->Panels, p);    return p;}void laShowPanel(laPanel *p){    p->Show = 1; laNotifyUsers("la.windows.panels_hidden");}void laShowPanelWithDropDownEffect(laPanel *p){    laShowPanel(p);    p->AnimationMode = LA_PANEL_ANIMATION_DROP_DOWN; laRefreshWindow();    p->AnimationRatio = 0;}void laShowPanelWithExpandEffect(laPanel *p){    laShowPanel(p);    p->AnimationMode = LA_PANEL_ANIMATION_EXPAND; laRefreshWindow();    p->AnimationRatio = 0;}void laHidePanel(laPanel *p){    if (!p->Mode) return;    p->Show = 0;    laNotifyUsers("la.windows.panels_hidden");}void laHidePanelWithDissoveEffect(laPanel *p){    if (!p->Mode) return;    laHidePanel(p);    p->AnimationMode = LA_PANEL_ANIMATION_DISSOVE; laRefreshWindow();    p->AnimationRatio = 1;}void laHidePanelWithCollapseEffect(laPanel *p){    if (!p->Mode) return;    laHidePanel(p);    p->AnimationMode = LA_PANEL_ANIMATION_COLLAPSE; laRefreshWindow();    p->AnimationRatio = 1;}void laHidePanelWithMinimizeEffect(laPanel *p){    if (!p->Mode) return;    laHidePanel(p);    p->AnimationMode = LA_PANEL_ANIMATION_MINIMIZE; laRefreshWindow();    p->AnimationRatio = 1;}void laActivatePanel(char* TemplateID, int x, int y){    laUiTemplate* uit = laFindUiTemplate(TemplateID);    laPanel *p = la_FindFreePanelByTemplate(MAIN.CurrentWindow, uit);    if (!p){ p=laCreateTopPanel(MAIN.CurrentWindow, TemplateID, x, y, 0,0, 0, 0, 0, 0, 0, 0, 0, 0); }    laShowPanelWithExpandEffect(p); laPopPanel(p);}void laPanPanel(laPanel *p, int DeltaX, int DeltaY){    p->UI.PanX += DeltaX;    p->UI.PanY += DeltaY;}int laPanUiListFree(laUiList *uil, int X, int Y){    uil->PanX+=X; uil->PanY+=Y;}int laPanUiList(laUiList *uil, int X, int Y, int L, int R, int U, int B){    if(uil->ScrollerShownH && !uil->ScrollerShownV){        if(Y){X+=Y;Y=0;}    }    if (Y > 0){        if (uil->B - uil->PanY <= B) return 0;        else{            uil->PanY += Y;            if (uil->B - uil->PanY <= B){                uil->PanY = uil->B - B;                return 1;            }        }    }    if (Y < 0){        if (uil->U - uil->PanY >= U) return 0;        else{            uil->PanY += Y;            if (uil->U - uil->PanY >= U){                uil->PanY = uil->U - U;                return 1;            }        }    }    if(uil->AllowScale){        laPanUiListFree(uil, X, 0);    }else{        if (X > 0){            if (uil->R - uil->PanX <= R) return 0;            else{                uil->PanX += X;                if (uil->R - uil->PanX <= R){                    uil->PanX = uil->R - R;                    return 1;                }            }        }        if (X < 0){            if (uil->L - uil->PanX >= L) return 0;            else{                uil->PanX += X;                if (uil->L - uil->PanX >= L){                    uil->PanX = uil->L - L;                    return 1;                }            }        }    }    return 1;}int laScaleUiList(laUiList *uil, real factor, int L, int R, int U, int B){    int ret=1;    if(!uil->AllowScale){ return 0; }    real NewScale=uil->Scale*factor;    if(NewScale<0.2){NewScale=0.2; ret=0;}    if(NewScale>5)  {NewScale=5; ret=0;}    if(NewScale>1-1e-4 && NewScale<1+1e-4){NewScale=1;}    factor=NewScale/uil->Scale;    uil->Scale=NewScale;    real mx=(L+R)/2,my=(U+B)/2;    real dx= (mx+uil->PanX)*factor;    real dy= (my+uil->PanY)*factor;    uil->PanX=dx-mx;    uil->PanY=dy-my;    MAIN.CurrentPanel->FrameDistinguish=100;    return ret;}int laPanUiListAuto(laUiList *uil, int X, int Y, int L, int R, int U, int B){    if(uil->AllowScale) return 0;    return laPanUiList(uil,X,Y,L,R,U,B);}laPanel *laDesignPropPanel(char *Title, int X, int Y, int W, int H,                           laUiDefineFunc Define, laPropPack *This, laPropPack *OperatorProps){    laPanel *p = la_NewPanel(0, X, Y, W, H, 0, H, 0, 0, 0, 0, 0, 0);    strSafeSet(&p->Title, Title);    if (Define){        Define(laPrepareUi(p), This, OperatorProps, NULL, 0);    }    //laui_DefaultOperatorPanelTitleBar(&p->TitleBar, &p->PP, OperatorProps, 0, 0);    p->BT= &_LA_THEME_FLOATING_PANEL;    p->Mode = LA_PANEL_FLOATING_PASSIVE;    p->BoundUi = 1;    return p;}laPanel *laDesignOperatorPanel(char *Title, int X, int Y, int W, int H, int MaxW, int MaxH, int MinW, int MinH, int SnapL, int SnapR, int SnapT, int SnapB,                               laUiDefineFunc Define, laPropPack *This, laPropPack *OperatorProps){    laPanel *p = la_NewPanel(0, X, Y, W, H, MaxW, MaxH, MinW, MinH, SnapL, SnapR, SnapT, SnapB);    strSafeSet(&p->Title, Title);    if (Define){        Define(laPrepareUi(p), This, OperatorProps, NULL, 0);    }    laui_DefaultOperatorPanelTitleBar(&p->TitleBar, &p->PP, OperatorProps, 0, 0);    p->BT= &_LA_THEME_FLOATING_PANEL;    p->Mode = LA_PANEL_FLOATING_TOP;    p->BoundUi = 1;    return p;}void laDeferredDestroyPanel(laPanel *p, int immediate){    laPanel *ip;    tnsDelete2DOffscreen(p->OffScr);    p->OffScr = 0;    strSafeDestroy(&p->Title);    if (!p->AnimationMode){        if (p->Parent) lstRemoveItem(&p->Parent->SubPanels, p);        else if (p->Mode == LA_PANEL_FLOATING_TOP){            lstRemoveItem(&MAIN.CurrentWindow->Panels, p);        }else if (p->Mode == LA_PANEL_NO_PARENT_MENU){            lstRemoveItem(&MAIN.CurrentWindow->Panels, p);        }else if (p->Block){            lstRemoveItem(&p->Block->Panels, p);            if (p->Block->CurrentPanel == p) p->Block->CurrentPanel = p->Block->Panels.pFirst;        }        laNotifyUsers("la.windows.panels");    }    for (ip = p->SubPanels.pFirst; ip; ip = ip->Item.pNext){        //lstRemoveItem(&p->SubPanels, ip);        laDestroySinglePanel(ip, immediate);        laNotifyUsers("la.windows.panels");    }    la_ClearDetachedProp(p);    memFree(p->PropLinkContainer); memFree(p->PropLinkFakeProp);    la_ReturnPanelNode(p);}void laDestroySinglePanel(laPanel *p, int immediate){    la_SetPropMathcerContext(p);    if (p->PropLinkPP.LastPs&&p->PropLinkPP.LastPs->p->SubProp->Props.pFirst){        for(laProp* prop=p->PropLinkPP.LastPs->p->SubProp->Props.pFirst;prop;prop=prop->Item.pNext){            { /* la_StopUsingPropPack(&prop->DetachedPP); */ }            //laStopUsingDataBlock(prop->DetachedPP.LastPs->UseInstance, prop->DetachedPP.LastPs->p,MAIN.PropMatcherContextP);        }    }    if(MAIN.CurrentWindow&&p==MAIN.CurrentWindow->MaximizedUiPanel){ laRestoreCanvasUI(); }    la_DestroyUiList(&p->UI, 1, 1, 0);    la_DestroyUiList(&p->TitleBar, 1, 1, 0);    //la_DestroyUiList(p->MenuRefer, 0, 1, 1);    if (p->Mode){        p->AnimationMode = LA_PANEL_ANIMATION_DISSOVE; laRefreshWindow();        p->AnimationRatio = p->CloseWhenMovedOut?0.0:1.0;    }    if (p->ParentOperator && la_UiOperatorExists(p)) ((laOperator *)p->ParentOperator)->OperatorPanel = 0;    if (la_UiStillInService(p)){        la_StopUiOperatorService(p);    }    if ((!p->AnimationMode) || immediate){        laDeferredDestroyPanel(p, immediate);    }else{        p->LaterDestroy = 1;    }}int laEnclosePanelContent(laPanel *p, laUiList *uil){    laBoxedTheme *bt = _LA_THEME_FLOATING_PANEL;    int MinW,MinWt=0;    int TitleReserve=p->Mode==LA_PANEL_FLOATING_TOP?LA_RH:0;    int CW = MAIN.CurrentWindow->CW;    if(p->SL && p->SR){return 0;}    la_SetPropMathcerContext(p);    la_UpdateUiListRecursive(&p->TitleBar, bt->TM, bt->LM, p->TW - bt->LM-bt->RM, p->TH, 0, p);    la_UpdateUiListRecursive(uil, bt->TM+p->TitleBar.B, 0, 1000, 0, 0, p);    MinWt = la_TestUiListMinumWidth(&p->TitleBar);    MinW = la_TestUiListMinumWidth(uil);    if (MinW<MinWt){MinW=MinWt;}    int ScrollerW=(uil->ScrollerShownV?(LA_SCROLL_W+bt->RM):0);    if (MinW > 20){        p->TW = MinW + bt->LM + bt->RM+ScrollerW;    }    la_PanelValidateWidth(p,uil);    laEnsurePanelInBound(p,uil);    if(p->TW>CW){ p->TW=CW; }    la_UpdateUiListRecursive(&p->TitleBar, bt->TM, bt->LM, p->TW - bt->LM-bt->RM, p->TH, 0, p);    la_UpdateUiListRecursive(uil, bt->TM+p->TitleBar.B, bt->LM, p->TW - bt->RM - ScrollerW, 0, 0, p);    laRedrawPanel(p);    return 1;}laPanel *laEnableIdlePanel(laPanel *Attachment, laOperator *a, laPropPack *OperatorProps, laUiDefineFunc ReplaceUiDefine, laPropPack *This,                               int L, int R, int B, int MaxGH, int MaxW, laEvent *e){    laOperator *ai = a;    laPanel *p;    int GX, GY, GW, t = 0;    int b;    laUiDefineFunc def = ReplaceUiDefine;    int MinW;    if (!def){ def=laui_DefaultPropDetails; }    GX = L; GY = B; GW = (R - L) > MaxW ? MaxW : (R - L);    p = laDesignPropPanel("TMP", GX, GY, GW, MaxGH, def, This, OperatorProps);    laEnclosePanelContent(p, &p->UI);    laSetOperatorLocalizer(p);    p->CloseWhenMovedOut=1;    laInvokeUi(a, "LA_menu_panel_operator", e, p, 0, 1);    //laShowPanelWithDropDownEffect(p);    if(!Attachment){ Attachment=MAIN.CurrentWindow->MaximizedUiPanel; }    if(Attachment){ p->Parent = Attachment; lstAppendItem(&Attachment->SubPanels, p); }    return p;}laPanel *laEnableSplashPanel(laUiDefineFunc ReplaceUiDefine, int L, int R, int B, int MaxGH, int MaxW, laEvent* e){    laPanel *p;    int GX, GY, GW, t = 0;    int b;    laUiDefineFunc def = ReplaceUiDefine;    int MinW;    if (!def) return 0;    GX = L; GY = B; GW = (R - L) > MaxW ? MaxW : (R - L);    p = laDesignPropPanel("TMP", GX, GY, GW, MaxGH, def, 0, 0);    p->Mode = LA_PANEL_FLOATING_TOP;    p->CloseWhenMovedOut=2; MAIN.PendingSplash=p;    laEnclosePanelContent(p, &p->UI);    if(MAIN.CurrentWindow->Operators.pFirst){        laSetOperatorLocalizer(MAIN.PendingSplash);        laInvokeUi(0, "LA_panel_operator", e, MAIN.PendingSplash, 0, 1);        MAIN.PendingSplash=0;    }    //laShowPanelWithExpandEffect(p);    lstPushItem(&MAIN.CurrentWindow->Panels, p);    return p;}laPanel *laEnablePropertyPanel(laPanel *Attachment, laOperator *a, laPropPack *OperatorProps, laUiDefineFunc ReplaceUiDefine, laUiDefineFunc FallBackUiDefine, laPropPack *This,                               int L, int R, int B, int MaxGH, int MaxW, laEvent *e){    laOperator *ai = a;    laPanel *p; laPropContainer* sub;    int GX, GY, GW, t = 0;    int b;    laUiDefineFunc def = ReplaceUiDefine;    int MinW;    if (!def){        if (This && This->LastPs->p){            if(This->LastPs->p->UiDefine) def = This->LastPs->p->UiDefine;            elif(This->LastPs->p->SubProp&&This->LastPs->p->SubProp->MenuUiDefine) def = This->LastPs->p->SubProp->MenuUiDefine;        }        if((!def) && (sub=la_EnsureSubTarget(This->LastPs->p,This->EndInstance)) && sub->MenuUiDefine) def=sub->MenuUiDefine;        if(!def) def = FallBackUiDefine?FallBackUiDefine:laui_DefaultPropUiDefine;    }    GX = L; GY = B;    GW = (R - L) > MaxW ? MaxW : (R - L);    p = laDesignPropPanel("TMP", GX, GY, GW, MaxGH, def, This, OperatorProps);    laEnclosePanelContent(p, &p->UI);    laSetOperatorLocalizer(p);    laInvokeUi(a, "LA_menu_panel_operator", e, p, 0, 1);    laShowPanelWithDropDownEffect(p);    if(!Attachment){ Attachment=MAIN.CurrentWindow->MaximizedUiPanel; }    if(Attachment){        p->Parent = Attachment;        lstAppendItem(&Attachment->SubPanels, p);    }    return p;}laPanel *laEnableEmptyPropertyPanel(laPanel *Attachment, laOperator *a, int L, int R, int U, int MaxGH, laEvent *e){    laPanel *p;    int t = 0;    int b;    //laLocalToWindow(0, Attachment, &L, &t);    //laLocalToWindow(0, Attachment, &R, &U);    p = laDesignPropPanel("TMP", L, U, R - L, MaxGH, 0, 0, 0);    laSetOperatorLocalizer(p);    laInvokeUi(a, "LA_menu_panel_operator", e, p, 0, 1);    laShowPanelWithDropDownEffect(p);    p->Parent = Attachment;    lstPushItem(&Attachment->SubPanels, p);    return p;}laPanel *laEnableMenuPanel(laPanel *Attachment, laOperator *a, laUiList *MenuRefer, laPropPack *This,                           int L, int R, int B, int MaxGH, int MaxW, laEvent *e){    laOperator *ai = a;    laPanel *p;    laBoxedTheme *bt = _LA_THEME_FLOATING_PANEL;    int GX, GY, GW, t = 0;    int b;    int MinW;    //laLocalToWindow(0,Attachment, &L, &t);    //laLocalToWindow(0,Attachment, &R, &B);    GX = L;    GY = B;    GW = (R - L) > MaxW ? MaxW : (R - L);    p = laDesignPropPanel("TMP", GX, GY, GW, MaxGH, 0, 0, 0);    p->MenuRefer = MenuRefer;    laEnclosePanelContent(p, MenuRefer);    laSetOperatorLocalizer(p);    laInvokeUi(a, "LA_menu_panel_operator", e, p, 0, 1);    laShowPanelWithDropDownEffect(p);    p->Parent = Attachment;    lstPushItem(&Attachment->SubPanels, p);    return p;}laPanel *laDefineAndEnableMenuPanel(laPanel *Attachment, laOperator *a, laPropPack *This,                                    int L, int B, int MaxGH, int MaxW, laEvent *e){    laOperator *ai = a;    laPanel *p;    int GX, GY, GW, t = 0;    int b;    GX = L;    GY = B;    GW = MaxW;    p = laDesignPropPanel("TMP", GX, GY, GW, MaxGH, 0, 0, 0);    p->MenuRefer = &p->UI;        p->Mode = LA_PANEL_NO_PARENT_MENU;    laSetOperatorLocalizer(p);    laInvokeUi(a, "LA_menu_panel_operator", e, p, 0, 1);    laShowPanelWithDropDownEffect(p);    if (Attachment){        p->Parent = Attachment;        lstPushItem(&Attachment->SubPanels, p);    }else{        lstPushItem(&MAIN.CurrentWindow->Panels, p);    }    return p;}laPanel *laEnableOperatorPanel(laOperator *For, laPropPack *This, int X, int Y, int W, int H, int MaxW, int MaxH, int MinW, int MinH, int SnapL, int SnapR, int SnapT, int SnapB, laEvent *e){    laOperator *ai = For;    laPanel *p;    int b;    laUiDefineFunc def = 0;    if (ai->Type->UiDefine) def = ai->Type->UiDefine;    else def = laui_DefaultPropUiDefine;        For->PP.EndInstance = For->CustomData;    p = laDesignOperatorPanel(ai->Type->Name, X, Y, W, H, MaxW, MaxH, MinW, MinH, SnapL, SnapR, SnapT, SnapB, def, This, &For->PP);    laEnclosePanelContent(p, &p->UI);    MAIN.ToPanel = p;    laShowPanelWithExpandEffect(p);    lstPushItem(&MAIN.CurrentWindow->Panels, p);    ai->OperatorPanel = p;    p->ParentOperator = For;    laInvokeUi(For, "LA_modal_panel_operator", 0, p, 0, 1);    return p;}laPanel *laEnableYesNoPanel(laOperator *a, laPanel *Attachment, char *Title, char *Message, int X, int Y, int W, laEvent *e){    laPanel *p; int b; laUiList *uil; laColumn* col;    p = la_NewPanel(0, X, Y, W, 0, 1000, 500, 50, 0, 0, 0, 0, 0);    strSafeSet(&p->Title, Title);    p->BoundUi = 1;    p->Mode = LA_PANEL_FLOATING_TOP;    p->BT = &_LA_THEME_FLOATING_PANEL;    MAIN.ToPanel = p;    laui_DefaultOperatorPanelTitleBar(&p->TitleBar, &p->PP, &p->PropLinkPP, 0, 0);    uil = laPrepareUi(p); col = laFirstColumn(uil);    laShowLabel(uil, col, Message, 0, 0)->Flags|=LA_TEXT_USE_NEWLINE|LA_TEXT_LINE_WRAP;    laUiItem* r=laBeginRow(uil,col,0,0);    laShowSeparator(uil,col)->Expand=1;    laShowItem(uil,col,0,"LA_confirm")->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_TEXT_ALIGN_CENTER;    laEndRow(uil,r);    laEnclosePanelContent(p,uil); laShowPanelWithExpandEffect(p);    lstPushItem(&MAIN.CurrentWindow->Panels, p);    laSetOperatorLocalizer(p);    laInvokeUi(a, "LA_modal_panel_operator", e, p, 0, 1);    return p;}laPanel *laEnableMessagePanel(laOperator *a, laPanel *Attachment, char *Title, char *Message, int X, int Y, int W, laEvent *e){    laPanel *p; int b; laUiList *uil; laColumn* col;    p = la_NewPanel(0, X, Y, W, 0, 1000, 0, 100, 0, 0, 0, 0, 0);    strSafeSet(&p->Title, Title);    p->BoundUi = 1;    p->Mode = LA_PANEL_FLOATING_TOP;    p->BT = &_LA_THEME_FLOATING_PANEL;    MAIN.ToPanel = p;    laui_DefaultOperatorPanelTitleBar(&p->TitleBar, &p->PP, &p->PropLinkPP, 0, 0);    uil = laPrepareUi(p); col = laFirstColumn(uil);    laShowLabel(uil, col, Message, 0, 0)->Flags|=LA_TEXT_USE_NEWLINE|LA_TEXT_LINE_WRAP;    laUiItem* r = laBeginRow(uil,col,0,0);    laShowSeparator(uil,col)->Expand=1;    laShowItemFull(uil,col,0,"LA_confirm",0,"text=Okay;",0,0)->Flags|=LA_UI_FLAGS_HIGHLIGHT;    laEndRow(uil, r);    laEnclosePanelContent(p,uil);    laShowPanelWithExpandEffect(p);    lstPushItem(&MAIN.CurrentWindow->Panels, p);    laSetOperatorLocalizer(p);    laInvokeUi(a, "LA_modal_panel_operator", e, p, 0, 1);    return p;}void laOperatorModalOver(laOperator* For){    For->ModalOver = 1;}void laDeferredRedraw(laPanel* p){    for(laListItemPointer* lip=MAIN.DeferredRedrawList.pFirst;lip;lip=lip->pNext){        if(lip->p==p) return;    }    lstAppendPointer(&MAIN.DeferredRedrawList, p);}void laRedrawAllWindows(){ if((!MAIN.CurrentWindow) || (!MAIN.CurrentWindow->win)) return;    laWindow* cur=MAIN.CurrentWindow;    for(laWindow* w=MAIN.Windows.pFirst;w;w=w->Item.pNext){        MAIN.CurrentWindow=w;        la_UpdateUiPlacement(w);    }    MAIN.CurrentWindow=cur;}void laRedrawCurrentWindow(){ if((!MAIN.CurrentWindow) || (!MAIN.CurrentWindow->win)) return;    if (MAIN.CurrentWindow) la_UpdateUiPlacement(MAIN.CurrentWindow);}void laRefreshWindow(){ MAIN.CurrentWindow->Redraw=1; }void laRedrawPanel(laPanel* p){ p->Refresh |= LA_TAG_REDRAW; MAIN.CurrentWindow->Redraw=1; }void laRecalcPanel(laPanel* p){ p->Refresh |= LA_TAG_RECALC; MAIN.CurrentWindow->Redraw=1; }void laRedrawCurrentPanel(){    if (MAIN.CurrentPanel) laRedrawPanel(MAIN.CurrentPanel);    elif (MAIN.CurrentWindow->MaximizedUiPanel) laRedrawPanel(MAIN.CurrentWindow->MaximizedUiPanel);}void laRecalcCurrentPanel(){    if (MAIN.CurrentPanel) laRecalcPanel(MAIN.CurrentPanel);    elif (MAIN.CurrentWindow->MaximizedUiPanel) laRecalcPanel(MAIN.CurrentWindow->MaximizedUiPanel);}void laRecalcPanelImmediate(laPanel* p){    p->FrameDistinguish++;    laBoxedTheme* bt = (*p->BT);    int scrollw=p->UI.ScrollerShownV?bt->RM*2+LA_SCROLL_W:0;    la_PanelRefreshDetachedProp(p);    int enclosed=0;    if(p->BoundUi || p->MenuRefer){        if(p->MenuRefer) enclosed=laEnclosePanelContent(p, p->MenuRefer);        else enclosed=laEnclosePanelContent(p, &p->UI);    }    if(!enclosed){        la_PanelValidateWidth(p,&p->UI);        laEnsurePanelInBound(p,p->MenuRefer?p->MenuRefer:&p->UI);        la_UpdateUiListRecursive(&p->TitleBar, bt->TM, bt->LM, p->TW-bt->RM, p->TH-bt->BM, 0, p);        int UseB=p->TitleBar.TB; if((!p->Mode)||(p->Mode==LA_PANEL_FLOATING_PASSIVE)){ UseB=0; }        la_UpdateUiListRecursive(&p->UI, UseB+bt->TM, bt->LM, p->TW-bt->RM-scrollw, p->TH-bt->BM, 0, p);    }    laWindow* w=MAIN.CurrentWindow;    if(w->MaximizedUiPanel==p&&w->MaximizedUi){ int CW = w->CW; int CH = w->CH;        laUiItem* ui=w->MaximizedUi; ui->TU=ui->U=0; ui->TB=ui->B=CH; ui->TL=ui->L=0; ui->TR=ui->R=CW;        if(!ui->Page) return; laBoxedTheme* bt=(*ui->Type->Theme);        la_UpdateUiListRecursive(ui->Page, ui->TU+bt->TM, ui->TL+bt->LM, ui->TR-bt->RM, ui->TB, 0, w->MaximizedUiPanel);    }}void laRecalcCurrentPanelImmediate(){    laRecalcPanelImmediate(MAIN.CurrentPanel);}int laNonFixedPanelExists(laPanel *p){    laPanel *ip;    if (!p) return 0;    //for (ip = MAIN.CurrentWindow->CurrentLayout->Panels.pLast; ip; ip = ip->Item.pPrev) {    //	if (ip == p) return 1;    //}    for (ip = MAIN.CurrentWindow->Panels.pLast; ip; ip = ip->Item.pPrev){        if (ip == p) return 1;    }    return 0;}int laIsInPanel(laPanel *p, int PanelX, int PanelY){    if (PanelX < 0 || PanelY < 0 || PanelY > p->H || PanelX > p->W) return 0;    return 1;}int laIsCloseToPanel(laPanel *p, int PanelX, int PanelY){    int tt=MAIN.TooltipCloseDistance;    if (PanelX < -tt || PanelY < -tt || PanelY > p->H+tt || PanelX > p->W+tt) return 0;    return 1;}int laPanelOverlappingEachOther(laPanel *p1, laPanel *p2){    if (p1->X > p2->X + p2->W || p1->X + p1->W < p2->X ||        p1->Y > p2->Y + p2->H || p1->Y + p1->H < p2->Y)        return 0;    return 1;}void laUnlinkSharedPanel(laPanel *p){    laWindow *w;    laPanel *ip;    for (w = MAIN.Windows.pFirst; w; w = w->Item.pNext){        for (ip = w->Panels.pFirst; ip; ip = ip->Item.pNext){            if (ip == p){                lstRemoveItem(&w->Panels, ip);                return;            }        }    }}int laIsPanelCovered(laPanel *p){    //laLayout* l = MAIN.CurrentWindow->CurrentLayout;    laPanel *ip;    laPanel *resp;    int in1 = 0, in2 = 0, in3 = 0;    laPanel *d1 = 0, *d2 = 0, *d3 = 0;    //for (ip = MAIN.CurrentWindow->CurrentLayout->Panels.pLast; ip; ip = ip->Item.pPrev) {    //	if (ip == p) { in1 = 1; d1 = 0; continue; }    //	if (ip->Show && laPanelOverlappingEachOther(ip, p)) d1 = ip;    //}    for (ip = MAIN.CurrentWindow->Panels.pLast; ip; ip = ip->Item.pPrev){        if (ip == p){            in3 = 1;            d3 = 0;            continue;        }        if (ip->Show && laPanelOverlappingEachOther(ip, p)) d3 = ip;    }    if (!in2 && !in3) in1 = 1;    if (in1){        if (d1 || d2 || d3) return 1;    }else{        if (in2){            if (d2 || d3) return 1;        }else if (in3)            if (d3) return 1;    }    return 0;}int laIsTopPanel(laPanel *p){    //if (!p->Item.pPrev) return 1;    //else {    if (!laIsPanelCovered(p)){        //laPopPanel(p);        return 1;    }    return 0;    //}    return 0;}void laWindowToLocal(laOperator *a, laPanel *p, int *x, int *y){    if(!p) return;    int ix = *x, iy = *y;    laListItemPointer *lip;    laOperator *ai = a;    (*x) = ix - ((MAIN.CurrentWindow->MaximizedUiPanel==p)?0: p->X);    (*y) = iy - ((MAIN.CurrentWindow->MaximizedUiPanel==p)?0: p->Y);    if (a){        for (lip = ai->LocalUiLists.pFirst; lip; lip = lip->pNext){            laUiList *uil = lip->p;            (*x) += uil->PanX;            (*y) += uil->PanY;        }    }}void laPanelToLocal(laOperator *a, int *x, int *y){    int ix = *x, iy = *y;    laListItemPointer *lip;    if (a){        for (lip = a->LocalUiLists.pFirst; lip; lip = lip->pNext){            laUiList *uil = lip->p;            (*x) += uil->PanX;            (*y) += uil->PanY;        }    }}void laLocalToWindow(laOperator *a, laPanel *p, int *x, int *y){    if(!p) return;    int ix = *x, iy = *y;    laListItemPointer *lip;    (*x) = ix + ((MAIN.CurrentWindow->MaximizedUiPanel==p)?0: p->X);    (*y) = iy + ((MAIN.CurrentWindow->MaximizedUiPanel==p)?0: p->Y);    if (a){        for (lip = a->LocalUiLists.pFirst; lip; lip = lip->pNext){            laUiList *uil = lip->p;            (*x) -= uil->PanX;            (*y) -= uil->PanY;        }    }}void laPanelToWindow(laPanel *p, int *x, int *y){    int ix = *x, iy = *y;    laListItemPointer *lip;    (*x) = ix + ((MAIN.CurrentWindow->MaximizedUiPanel==p)?0: p->X);    (*y) = iy + ((MAIN.CurrentWindow->MaximizedUiPanel==p)?0: p->Y);}void laLocalToPanel(laOperator *a, int *x, int *y){    int ix = *x, iy = *y;    laListItemPointer *lip;    if (a){        for (lip = a->LocalUiLists.pFirst; lip; lip = lip->pNext){            laUiList *uil = lip->p;            (*x) -= uil->PanX;            (*y) -= uil->PanY;        }    }}void laSetNextMenuPos(int X, int Y, int W, int H){    MAIN.NextX = X;    MAIN.NextY = Y;    MAIN.NextW = W;    MAIN.NextH = H;}int laIsInBlock(laBlock *b, int X, int Y){    if (X >= b->X && X <= b->X + b->W && Y >= b->Y && Y <= b->Y + b->H) return 1;    return 0;}int laIsInBlockHeader(laBlock *b, int X, int Y){ if (X >= b->X && X <= b->X + b->W && Y >= b->Y && Y <= b->Y + LA_RH) return 1; return 0; }int laIsInBlockBotton1(laBlock *b, int X, int Y){ if (X >= b->X && X <= b->X + LA_RH && Y >= b->Y && Y <= b->Y + LA_RH) return 1; return 0; }int laIsInBlockBotton2(laBlock *b, int X, int Y){ if (X >= b->X+LA_RH && X <= b->X+LA_2RH && Y >= b->Y && Y <= b->Y + LA_RH) return 1; return 0; }laBlock *laClearBlockButtonRecursive(laBlock *b, laBlock *except){    if(b->B1){laClearBlockButtonRecursive(b->B1,except);}    if(b->B2){laClearBlockButtonRecursive(b->B2,except);}    if (!b->B1 && !b->B2){        if(b!=except && b->OnButton){ b->OnButton=0; laRefreshWindow(); }    }}laBlock *laDetectBlockRecursive(laBlock *b, int X, int Y){    laPanel *p;    laBlock *sb = 0;    if (!laIsInBlock(b, X, Y)) return 0;    if (!b->B1 && !b->B2) return b;    if (sb = laDetectBlockRecursive(b->B1, X, Y)) return sb;    return laDetectBlockRecursive(b->B2, X, Y);}laPanel *laDetectPanel(int X, int Y){    laPanel *p; laBlock *b;    for (p = MAIN.CurrentWindow->Panels.pFirst; p; p = p->Item.pNext){        int x = X, y = Y;        laWindowToLocal(0, p, &x, &y);        if (p->Show && laIsInPanel(p, x, y)){            return p;        }    }    if(MAIN.CurrentWindow->MaximizedUiPanel){return 0;}    laBlock* RootBlock=MAIN.CurrentWindow->MaximizedBlock?MAIN.CurrentWindow->MaximizedBlock:MAIN.CurrentWindow->CurrentLayout->FirstBlock;    if (b = laDetectBlockRecursive(RootBlock, X, Y)) return b->CurrentPanel;    return 0;}laUiList *laPrepareUi(laPanel *p){    return &p->UI;}laColumn *laFirstColumn(laUiList *uil){    if (uil->Columns.pFirst) return uil->Columns.pFirst;    else{        laColumn *c = memAcquireSimple(sizeof(laColumn));        c->SP = 1;        c->PreWidth = 1;        lstAppendItem(&uil->Columns, c);        c->Top = c;        return uil->Columns.pFirst;    }}laColumn *laSplitColumn(laUiList *uil, laColumn *c, real Percent){    laColumn *lc, *rc;    if (c->LS || c->RS) return c;    lc = memAcquireSimple(sizeof(laColumn));    rc = memAcquireSimple(sizeof(laColumn));    c->LS = lc;    c->RS = rc;    c->LS->SP = Percent;    c->RS->SP = Percent;    c->LS->Top = c->Top;    c->RS->Top = c->Top;    if (uil){        lstAppendItem(&uil->Columns, lc);        lstAppendItem(&uil->Columns, rc);    }    if (c->LS && c->RS->MaxW == 0){        c->LS->PreWidth = c->PreWidth * c->LS->SP;        c->RS->PreWidth = c->PreWidth * (1 - c->RS->SP);    }else if (c->RS && c->LS->MaxW == 0){        c->LS->PreWidth = c->PreWidth * c->LS->SP;        c->RS->PreWidth = c->PreWidth * (1 - c->RS->SP);    }    return c;}laColumn *laLeftColumn(laColumn *c, int MaxWidth){    if (c->LS && MaxWidth) c->LS->MaxW = MaxWidth;    return c->LS;}laColumn *laRightColumn(laColumn *c, int MaxWidth){    if (c->LS && c->LS->MaxW && MaxWidth) return c->RS;    if (MaxWidth) c->RS->MaxW = MaxWidth;    return c->RS;}void la_DestroyColumnRecursive(laListHandle *List, laColumn *c){    lstRemoveItem(List, c);    if (c->LS) la_DestroyColumnRecursive(List, c->LS);    if (c->RS) la_DestroyColumnRecursive(List, c->RS);    memFree(c);}int laCheckAndMergeSubColumnsUiList(laUiList *TopUil, laColumn *c, int DoMerge){    laUiList *uil = TopUil;    laUiList *sub;    laUiItem *ui;    laColumn *cc, *NextCC = 0;    int Occupied = 0;    int Removed = 0;    if (!c->LS) return 0;    else{        laCheckAndMergeSubColumnsUiList(TopUil, c->LS, DoMerge);        laCheckAndMergeSubColumnsUiList(TopUil, c->RS, DoMerge);    }    for (ui = TopUil->UiItems.pFirst; ui; ui = ui->Item.pNext){        if (ui->C == c->LS || ui->C == c->RS){            if (DoMerge){                ui->C = c;                Occupied = 1;            }else                return 1;        }        if (ui->Subs.pFirst){            for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){                laCheckAndMergeSubColumnsUiList(sub, c, DoMerge);            }        }    }    if (!Removed){        for (cc = uil->Columns.pFirst; cc; cc = cc->Item.pNext){            if (cc == c){                if (c->LS) la_DestroyColumnRecursive(&uil->Columns, c->LS);                if (c->RS) la_DestroyColumnRecursive(&uil->Columns, c->RS);                c->LS = 0;                c->RS = 0;                Removed = 1;                break;            }        }    }    return Occupied;}laPropContainer* laUiHasExtraProps(laUiType *ut, int size, int Hyper){    ut->ExtraProps = laAddPropertyContainer(ut->Identifier, 0,0,U'◳',0,size,0,0,Hyper);    ut->FakeProp = memAcquire(sizeof(laSubProp));    ut->FakeProp->Base.SubProp = ut->ExtraProps;    ut->FakeProp->Base.Identifier = ut->Identifier;    ut->FakeProp->Base.PropertyType = LA_PROP_SUB;    ut->FakeProp->Base.Offset = offsetof(laUiItem, Extra);    ut->FakeProp->Base.OffsetIsPointer = 1;    //ut->FakeProp->Base.Container = ut->ExtraProps;    return ut->ExtraProps;}laPropContainer* laCanvasHasExtraProps(laCanvasTemplate *ct, int size, int Hyper){    ct->ExtraProps = laAddPropertyContainer(ct->Identifier->Ptr, 0,0,U'◳',0,size,0,0,Hyper);    ct->FakeProp = memAcquire(sizeof(laSubProp));    ct->FakeProp->Base.SubProp = ct->ExtraProps;    ct->FakeProp->Base.Identifier = ct->Identifier->Ptr;    ct->FakeProp->Base.PropertyType = LA_PROP_SUB;    ct->FakeProp->Base.Offset = offsetof(laUiItem, Extra);    ct->FakeProp->Base.OffsetIsPointer = 1;    //ut->FakeProp->Base.Container = ut->ExtraProps;    return ct->ExtraProps;}void la_DestroyUiType(laUiType* uit){    laKeyMapItem* kmi; while(kmi=lstPopItem(&uit->KeyMapper.Items)){ la_FreeKeyMapItem(kmi); }    memFree(uit);}laUiType *la_RegisterUiType(const char *Identifer, int ForType, const char *UseOperator, laBoxedTheme **bt, laUiDrawFunc *Draw, laUiGetHeightFunc GetHeight, laUiInitFunc Init, laUiDestroyFunc Destroy){    laUiType *ut = memAcquire(sizeof(laUiType));    ut->Identifier = Identifer;    ut->OperatorID = UseOperator;    ut->Draw = Draw;    ut->Theme = bt;    ut->ForType = ForType;    ut->OperatorType = laGetOperatorType(UseOperator);    ut->GetHeight = GetHeight;    ut->Init = Init;    ut->Destroy = Destroy;    la_UDFAppendSharedTypePointer(Identifer, ut);    lstAppendItem(&MAIN.UiTypes, ut);    return ut;}laUiType *la_GetUiTypeFromProperty(laProp *P){    laUiType *ut = MAIN.UiTypes.pFirst;    if (!P) return 0;    if (P->DefaultUiType) return P->DefaultUiType;    if (P->SubProp == LA_PC_SOCKET_IN || P->SubProp == LA_PC_SOCKET_OUT) return _LA_UI_NODE_SOCKET;     if (P->PropertyType == LA_PROP_SUB) return _LA_UI_COLLECTION;    for (ut; ut; ut = ut->Item.pNext){        if ((ut->ForType&LA_PROP_GENERIC_BITS) == (P->PropertyType&LA_PROP_GENERIC_BITS)){            return ut;        }    }    return 0;}laUiType *la_GetUiButtonType(){    laUiType *ut = MAIN.UiTypes.pFirst;    for (ut; ut; ut = ut->Item.pNext){        if (ut->ForType == LA_PROP_OPERATOR) return ut;    }    return 0;}laCanvasTemplate *la_GetCanvasTemplate(char* TargetContainerID, char* TemplateID){    laCanvasTemplate *vdt;    for (vdt = MAIN.View2DTemplates.pFirst; vdt; vdt = vdt->Item.pNext){        if (strSame(TemplateID, vdt->Identifier->Ptr) || strSame(TargetContainerID, vdt->TargetContainerID)) return vdt;    }    return 0;}void la_AssignPropExtras(laUiItem* ui){    if(!ui->Type || !ui->Type->FakeProp) return;    ui->FakePs.p = ui->Type->FakeProp;    ui->FakePs.Type = U'.';    ui->FakePs.UseInstance = ui;    ui->ExtraPP.LastPs = &ui->FakePs;}void la_AssignCanvasPropExtras(laUiItem* ui){    if(!ui->CanvasTemplate || !ui->CanvasTemplate->FakeProp) return;    laCanvasTemplate*ct=ui->CanvasTemplate;    ui->FakePs.p = ct->FakeProp;    ui->FakePs.Type = U'.';    ui->FakePs.UseInstance = ui;    ui->ExtraPP.EndInstance = ui->Extra;    ui->ExtraPP.LastPs = &ui->FakePs;}laUiItem *la_UpdatePropDisplay(laUiItem *ui, laPropPack *Base, const char *Path, laUiDefineFunc Template, laWidget* Widget, char* instructions){    int result;    if (!ui) return 0;    laUiType* OverrideType=Widget&&Widget->Type?Widget->Type:0;    if (Path){        result = la_GetPropFromPath(&ui->PP, Base, Path, 0);        if (!result){            ui->AT = laGetOperatorType(Path);            if (!ui->AT /* && !OverrideType*/) return la_UpdatePropDisplay(ui, 0, "la.unknown_prop", 0, 0, instructions);            ui->Type = la_GetUiButtonType();            if (OverrideType && (OverrideType->ForType == LA_PROP_OPERATOR)) ui->Type = OverrideType;        }else{            ui->Type = (OverrideType && ((!OverrideType->ForType)||                                        (OverrideType->ForType&&OverrideType->ForType == ui->PP.LastPs->p->PropertyType)||                                        (OverrideType->TargetSub && !strcmp(OverrideType->TargetSub, ui->PP.LastPs->p->Identifier)))) ?                                            OverrideType : la_GetUiTypeFromProperty(ui->PP.LastPs->p);            ui->Flags|=ui->PP.LastPs->p->DefaultFlags;        }        if (Base){            ui->PP.RawThis = Base;        }    }else if (Base){        ui->PP.LastPs = Base->LastPs;        ui->Type = (OverrideType && ((!OverrideType->ForType)||                                    (OverrideType->ForType&&OverrideType->ForType == ui->PP.LastPs->p->PropertyType)||                                    (OverrideType->TargetSub && !strcmp(OverrideType->TargetSub, ui->PP.LastPs->p->SubProp->Identifier)))) ?                                        OverrideType : la_GetUiTypeFromProperty(ui->PP.LastPs->p);        ui->PP.RawThis = Base; //HACK! Not Unified For Prop Access!!!<<<----------??????????        ui->Flags|=ui->PP.LastPs->p->DefaultFlags;    }    la_AssignPropExtras(ui);    if(Widget){ ui->Flags|= Widget->Flags; }    if(Template) ui->Template = Template; ui->State = LA_UI_NORMAL;    if(!ui->Type) ui->Type = Widget?Widget->Type:0;    if(instructions) strSafeSet(&ui->ExtraInstructions, instructions);    return ui;}laUiItem *la_UpdateLabelDisplay(laUiItem *ui, laUiDefineFunc Template, char *Content){    ui->Type = _LA_UI_LABEL;    ui->Template = Template;    ui->State = LA_UI_NORMAL;    strSafeSet(&ui->Display, Content);    la_AssignPropExtras(ui);    return ui;}laUiItem *la_CreateGroupHandle(laWidget* Widget){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    ui->Type = (Widget&&Widget->Type)?Widget->Type : _LA_UI_FIXED_GROUP;    ui->State = LA_UI_NORMAL;    la_AssignPropExtras(ui);    return ui;}laUiItem *laShowLabel(laUiList *uil, laColumn *c, const char *Content, laUiDefineFunc Template, laWidget* Widget){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    transLate(Content);    la_UpdateLabelDisplay(ui, Template, Content);    ui->C = c;    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laShowLabelDynamic(laUiList *uil, laColumn *c, const char *Content, laUiDefineFunc Template, laWidget* Widget){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    la_UpdateLabelDisplay(ui, Template, Content);    ui->C = c;    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laShowIcon(laUiList *uil, laColumn *c, laPropPack *Base, const char *Path, laWidget* Widget){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    la_UpdatePropDisplay(ui, Base, Path, 0, Widget, 0);    ui->Flags |= LA_UI_FLAGS_INT_ICON;    ui->C = c;    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laShowInvisibleItem(laUiList *uil, laColumn *c, laPropPack *Base, const char *Path){    laWidget wg={&_LA_UI_INVISIBLE, 0}; return laShowItemFull(uil,c,Base,Path,&wg,0,0,0);}laUiItem *laShowItem(laUiList *uil, laColumn *c, laPropPack *Base, const char *Path){    return laShowItemFull(uil,c,Base,Path,0,0,0,0);}laUiItem *laShowItemFull(laUiList *uil, laColumn *c, laPropPack *Base, const char *Path, laWidget* Widget, char* instructions, laUiDefineFunc Template, int TemplateContext){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    la_UpdatePropDisplay(ui, Base, Path, Template, Widget, instructions);    ui->C = c;    ui->TemplateContext = TemplateContext;    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;        lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laShowImage(laUiList *uil, laColumn *c, tnsImage* Image, int Height){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    ui->C = c; ui->Extra=Image;    ui->Type=_LA_UI_IMAGE; ui->Type->Init(ui);    ui->SymbolID=Height;    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laShowNodeSocket(laUiList *uil, laColumn *c, laPropPack *Base, const char *Path, char* instructions){    return laShowItemFull(uil,c,Base,Path,LA_WIDGET_NODE_SOCKET,instructions,0,0);}laUiItem *laShowHeightAdjuster(laUiList *uil, laColumn *c, laPropPack *Base, const char *Path, char* instructions){    return laShowItemFull(uil,c,Base,Path,LA_WIDGET_HEIGHT_ADJUSTER,instructions,0,0);}laUiItem *laShowCanvas(laUiList *uil, laColumn *c, laPropPack *Base, const char *Path, const char *id2DTemplate, int Height){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    ui->Type = _LA_UI_CANVAS;    ui->State = LA_UI_NORMAL;    ui->C = c;    la_GetPropFromPath(&ui->PP, Base, Path, 0);    if (id2DTemplate) ui->CanvasTemplate = la_GetCanvasTemplate(0, id2DTemplate);    else{        if(!ui->PP.LastPs || ui->PP.LastPs->p->PropertyType!=LA_PROP_SUB){ la_FreePropStepCache(ui->PP.Go); memFree(ui); return laShowItem(uil,c,Base,Path); }        laSubProp* sp=ui->PP.LastPs->p; ui->PP.LastPs->p->SubProp=la_EnsureSubTarget(sp,0);        ui->CanvasTemplate = la_GetCanvasTemplate(sp->TargetID, 0);        if(!ui->CanvasTemplate){ la_FreePropStepCache(ui->PP.Go); memFree(ui); return laShowItem(uil,c,Base,Path); }    }    if (ui->Type->Init) ui->Type->Init(ui);    la_AssignCanvasPropExtras(ui);    if (Height) ui->Expand=Height; else ui->Expand=6;    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laShow3DCanvasCombo(laUiList *uil, laColumn *c, laPropPack *Base, const char *Path, int Height, laPropPack* Detached){    laUiItem* ui=0;#define ADD_CANVAS \    laUiItem* b=laBeginRow(uil,cr,0,0);\    laUiItem* b3=laOnConditionThat(uil,cr,laPropExpression(&rb->PP,"active"));{\        laShowLabel(uil,cr,"⯈",0,0); laShowItem(uil,cr,&rb->PP,"active.name")->Flags|=LA_UI_FLAGS_NO_DECAL;\    }laEndCondition(uil,b3);\    laEndRow(uil,b);        if(Detached){        laColumn* cl,*cll,*clr,*cr;        laSplitColumn(uil,c,0.35); cl=laLeftColumn(c,7); cr=laRightColumn(c,0);        laSplitColumn(uil,cl,0.4); cll=laLeftColumn(cl,1); clr=laRightColumn(cl,0);        laShowItemFull(uil,cll,Detached,"detached",0,0,0,0)->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_ICON;        laUiItem* b2=laOnConditionThat(uil,c,laPropExpression(Detached,"detached"));{            laUiItem* rb=laShowItemFull(uil,clr,Detached,"root_object",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);            ADD_CANVAS            ui=laShowCanvas(uil,c,Detached,"root_object",0,Height); laDefault3DViewOverlay(ui);        }laElse(uil,b2);{            laUiItem* rb=laShowItemFull(uil,clr,0,"tns.world.active_root",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);            ADD_CANVAS            ui=laShowCanvas(uil,c,0,"tns.world.active_root",0,Height); laDefault3DViewOverlay(ui);        }laEndCondition(uil,b2);    }else{        ui=laShowCanvas(uil,c,Base,Path,0,Height); laDefault3DViewOverlay(ui);    }#undef ADD_CANVAS}laUiItem *laShowColumnAdjuster(laUiList *uil, laColumn *c){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    laCanvasExtra *e;    ui->Type = _LA_UI_COLUMN_ADJUSTER;    ui->Flags |= LA_WIDGET_COLUMN_ADJUSTER->Flags;    ui->C = c;    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;        lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laShowSymbol(laUiList *uil, laColumn *c, int SymbolID, int Height){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    ui->Type = _LA_UI_SYMBOL;    ui->SymbolID = SymbolID;    if (Height) ui->State = Height;    ui->C = c;    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;        lstAppendItem(&uil->UiItems, ui);    return ui;}laPropPack* laShowCompoundValue(laUiItem* ui, int slot, laPropPack *Base, const char *Path){    laPropPack PP={0}; int result;    if (Path){        result = la_GetPropFromPath(&PP, Base, Path, 0);        if (!result){ return 0; }        if (Base){ PP.RawThis = Base; }    }else if (Base){        PP.LastPs = Base->LastPs; PP.RawThis = Base; //HACK! Not Unified For Prop Access!!!<<<----------??????????    }    laCompoundPP* CPP = memAcquire(sizeof(laCompoundPP));    CPP->Slot = slot; memcpy(&CPP->PP, &PP, sizeof(laPropPack));    lstAppendItem(&ui->CompoundPPs,CPP);    return &CPP->PP;}laUiItem *laBeginRow(laUiList *uil, laColumn *c, int Expand, int Even){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    ui->Type = &_LA_UI_ROW_BEGIN;    ui->State=Expand;    ui->Flags=Even;    ui->C = c;    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;        lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laEndRow(laUiList *uil, laUiItem* Begin){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    ui->Type = &_LA_UI_ROW_END;    ui->C = Begin->C;    ui->Page = (laUiList*)Begin;    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;        lstAppendItem(&uil->UiItems, ui);    return ui;}void la_ConditionerInit(laUiItem *ui, laUiConditionNode *Expression){    laConditionUiExtraData *e = CreateNew(laConditionUiExtraData);    e->Expression = Expression;    ui->Extra = e;    la_AssignPropExtras(ui);}laUiItem *laMakeGroup(laUiList *uil, laColumn *c, const char *Name, laWidget* Widget){    laUiItem *ui = la_CreateGroupHandle(Widget);    laUiList *nuil;    ui->C = c;    lstAppendItem(&uil->UiItems, ui);    nuil = memAcquireSimple(sizeof(laUiList));    strSafeSet(&nuil->TabName, Name);    ui->Page = nuil;    lstAppendItem(&ui->Subs, nuil);    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;        return ui;}laUiItem *laMakeFoldableGroup(laUiList *uil, laColumn *c, const char *Name, laWidget* Widget, int DefaultFolded, int ButtonFlags){    laUiItem *SubUi = laMakeGroup(uil, c, Name, Widget?Widget:0);    laUiList *sub = SubUi->Page;    laColumn *s = laFirstColumn(sub);    SubUi->State = LA_UI_ACTIVE;    laUiItem *b1 = laOnConditionToggle(sub, s, 0, 0, 0, 0, 0);    strSafePrint(&b1->ExtraInstructions, "text=… %s", Name);    if(!DefaultFolded) b1->State=LA_UI_ACTIVE;    if(ButtonFlags)b1->Flags|=ButtonFlags; else b1->Flags|=LA_UI_FLAGS_NO_DECAL;    laShowSeparator(sub, s);    return SubUi;}laUiItem *laMakeEmptyGroup(laUiList *uil, laColumn *c, const char *Name, laWidget* Widget){    laUiItem *SubUi = laMakeGroup(uil, c, Name, Widget?Widget->Type:0);    laUiList *sub = SubUi->Page;    laColumn *s = laFirstColumn(sub);    SubUi->State = LA_UI_ACTIVE;    return SubUi;}void laEndFoldableGroup(laUiList *sub, laUiItem *group){    laEndCondition(sub, sub->UiItems.pFirst);}laUiItem *laMakeTab(laUiList *uil, laColumn *c, laWidget* Widget){    laUiItem *ui = la_CreateGroupHandle(Widget?Widget:LA_WIDGET_TAB);    laUiList *nuil;    ui->C = c;    lstAppendItem(&uil->UiItems, ui);    if (ui->Type->Init) ui->Type->Init(ui);    ui->ExtraPP.EndInstance = ui->Extra;        return ui;}laUiList *laAddTabPage(laUiItem *ui, const char *Name){    laUiList *uil = memAcquireSimple(sizeof(laUiList));    if (!ui->Page) ui->Page = uil;    lstAppendItem(&ui->Subs, uil);    strSafeSet(&uil->TabName, Name);    laFirstColumn(uil);    //laFirstColumn(uil);    return uil;}laUiList *la_AddInstancePage(laUiItem *ui, void *Instance, laWidget* Widget){    laUiList *uil = memAcquireSimple(sizeof(laUiList));    /*if (!ui->Page) */ ui->Page = uil;    lstAppendItem(&ui->Subs, uil);    uil->Instance = Instance; ui->PP.EndInstance=Instance;    return uil;}laUiConditionNode *laTrue(){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_TRUE;    return ucn;}laUiConditionNode *laFalse(){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_FALSE;    return ucn;}laUiConditionNode *laPropExpression(laPropPack *Base, char *Prop){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_PROP;    la_GetPropFromPath(&ucn->PP, Base, Prop, 0);    strSafeSet(&ucn->String, Prop);    return ucn;}laUiConditionNode *laIntExpression(int Value){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_INT;    ucn->IntValue = Value;    return ucn;}laUiConditionNode *laFloatExpression(real Value){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_FLOAT;    ucn->FloatValue = Value;    return ucn;}laUiConditionNode *laStringExpression(char *Content){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_STRING;    strSafeSet(&ucn->String, Content);    return ucn;}laUiConditionNode *laAnd(laUiConditionNode *Expression1, laUiConditionNode *Expression2){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_AND;    ucn->Expression1 = Expression1;    ucn->Expression2 = Expression2;    return ucn;}laUiConditionNode *laOr(laUiConditionNode *Expression1, laUiConditionNode *Expression2){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_OR;    ucn->Expression1 = Expression1;    ucn->Expression2 = Expression2;    return ucn;}laUiConditionNode *laNot(laUiConditionNode *Expression1){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_NOT;    ucn->Expression1 = Expression1;    return ucn;}laUiConditionNode *laEqual(laUiConditionNode *Expression1, laUiConditionNode *Expression2){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_EQ;    ucn->Expression1 = Expression1;    ucn->Expression2 = Expression2;    return ucn;}laUiConditionNode *laGreaterThan(laUiConditionNode *Expression1, laUiConditionNode *Expression2){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_GT;    ucn->Expression1 = Expression1;    ucn->Expression2 = Expression2;    return ucn;}laUiConditionNode *laLessThan(laUiConditionNode *Expression1, laUiConditionNode *Expression2){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_LT;    ucn->Expression1 = Expression1;    ucn->Expression2 = Expression2;    return ucn;}laUiConditionNode *laGreaterEqual(laUiConditionNode *Expression1, laUiConditionNode *Expression2){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_GE;    ucn->Expression1 = Expression1;    ucn->Expression2 = Expression2;    return ucn;}laUiConditionNode *laLessEqual(laUiConditionNode *Expression1, laUiConditionNode *Expression2){    laUiConditionNode *ucn = memAcquireSimple(sizeof(laUiConditionNode));    ucn->Type = LA_CONDITION_LE;    ucn->Expression1 = Expression1;    ucn->Expression2 = Expression2;    return ucn;}int la_GetIntConditionValue(laUiConditionNode *Expression){    if (Expression->Type != LA_CONDITION_INT) return 0;    return Expression->IntValue;}real la_GetFloatConditionValue(laUiConditionNode *Expression){    if (Expression->Type != LA_CONDITION_FLOAT) return 0;    return Expression->FloatValue;}char *la_GetStringConditionValue(laUiConditionNode *Expression){    return Expression->String->Ptr;}int la_DoCompare(int CompMode, int Mode1, int i1, real f1, char *s1, void *p1, int Mode2, int i2, real f2, char *s2, void *p2){    switch (Mode1){    case LA_PROP_ENUM:    case LA_PROP_INT:    case LA_CONDITION_INT:        switch (Mode2){        case LA_PROP_ENUM:        case LA_PROP_INT:        case LA_CONDITION_INT:            switch (CompMode){            case LA_CONDITION_GE:                return (i1 >= i2);            case LA_CONDITION_GT:                return (i1 > i2);            case LA_CONDITION_EQ:                return (i1 == i2);            case LA_CONDITION_LT:                return (i1 < i2);            case LA_CONDITION_LE:                return (i1 <= i2);            }        case LA_PROP_FLOAT:        case LA_CONDITION_FLOAT:            switch (CompMode){            case LA_CONDITION_GE:                return ((real)i1 >= f2);            case LA_CONDITION_GT:                return ((real)i1 > f2);            case LA_CONDITION_EQ:                return ((real)i1 >= f2 - 0.0001 && (real)i1 <= f2 + 0.0001);            case LA_CONDITION_LT:                return ((real)i1 < f2);            case LA_CONDITION_LE:                return ((real)i1 <= f2);            }        case LA_PROP_SUB:            if (CompMode == LA_CONDITION_EQ) return i1 == (int)p2;        default:            return 0;        }    case LA_PROP_FLOAT:    case LA_CONDITION_FLOAT:        switch (Mode2){        case LA_PROP_INT:        case LA_PROP_ENUM:        case LA_CONDITION_INT:            switch (CompMode){            case LA_CONDITION_GE:                return (f1 >= (real)i2);            case LA_CONDITION_GT:                return (f1 > (real)i2);            case LA_CONDITION_EQ:                return (f1 + 0.0001 >= (real)i2 && f1 - 0.0001 <= (real)i2);            case LA_CONDITION_LT:                return (f1 < (real)i2);            case LA_CONDITION_LE:                return (f1 <= (real)i2);            }        case LA_PROP_FLOAT:        case LA_CONDITION_FLOAT:            switch (CompMode){            case LA_CONDITION_GE:                return (f1 >= f2);            case LA_CONDITION_GT:                return (f1 > f2);            case LA_CONDITION_EQ:                return (f1 == f2);            case LA_CONDITION_LT:                return (f1 < f2);            case LA_CONDITION_LE:                return (f1 <= f2);            }        default:            return 0;        }    case LA_PROP_STRING:    case LA_CONDITION_STRING:        switch (Mode2){        case LA_PROP_STRING:        case LA_CONDITION_STRING:            return strSame(s1, s2);        default:            return 0;        }    case LA_PROP_SUB:        switch (Mode2){        case LA_PROP_SUB:            return p1 == p2;        case LA_CONDITION_INT:        case LA_PROP_INT:        case LA_PROP_ENUM:            return (int)p1 == i2;        default:            return 0;        }    default:        switch (CompMode){        case LA_CONDITION_GE:            return (i1 >= i2);        case LA_CONDITION_GT:            return (i1 > i2);        case LA_CONDITION_EQ:            return (i1 == i2);        case LA_CONDITION_LT:            return (i1 < i2);        case LA_CONDITION_LE:            return (i1 <= i2);        }    }}int la_DoExpression(laUiConditionNode *Expression, int *IResult, real *FResult, char *_StrResult, void **PtrResult){    void *Instance = 0;    int IValue1 = 0, IValue2 = 0;    real FValue1 = 0, FValue2 = 0;    void *Ptr1 = 0, *Ptr2 = 0;    char Str1[128], Str2[128]={0}; char* StrResult=_StrResult;    int Result1, Result2;    laEnumItem *ei; laSubProp*sp;    if (!Expression) return 0;    Str1[0] = 0;    Str2[0] = 0;    laPropIterator pi = {0};    switch (Expression->Type){    case LA_CONDITION_PROP:        if (!Expression->PP.LastPs){            (*IResult) = 0;            return 0;        }        switch (Expression->PP.LastPs->p->PropertyType){        case LA_PROP_INT:            *IResult = laGetInt(&Expression->PP);            if (*IResult) return LA_CONDITION_INT;            else return 0;        case LA_PROP_FLOAT:            *FResult = laGetFloat(&Expression->PP);            if (*FResult) return 1;            else return 0;            break;        case LA_PROP_STRING:            laGetString(&Expression->PP, _StrResult, &StrResult);            if (StrResult[0]) return 1;            else return 0;            break;        case LA_PROP_ENUM:            ei = laGetEnum(&Expression->PP);            if (!ei) return 0;            /*if(ei) */ *IResult = ei->Index;            if (*IResult) return LA_CONDITION_INT;            else return 0;            break;        case LA_PROP_SUB:            sp=Expression->PP.LastPs->p;            //if (sp->IsDetached){ *PtrResult = sp->Detached; if (sp->Detached) return 1; else return 0; }            if (!Expression->PP.Go) Instance = Expression->PP.EndInstance;            else Instance = laGetActiveInstance(Expression->PP.LastPs->p, Expression->PP.LastPs->UseInstance, &pi);            if(!Instance){ Expression->PP.LastPs->p; if((!sp->GetActive) && (sp->Base.Offset<=0)){                     Instance=laGetInstance(sp,Expression->PP.LastPs->UseInstance, &pi);                }            }            *PtrResult = Instance;            if (Instance) return 1;            break;        default:            return 0;        }        break;    case LA_CONDITION_INT:        *IResult = Expression->IntValue;        if (*IResult) return 1;        else            return 0;    case LA_CONDITION_FLOAT:        *FResult = Expression->FloatValue;        if (*FResult) return 1;        else            return 0;    case LA_CONDITION_STRING:        if (Expression->String){            strCopyFull(StrResult, Expression->String->Ptr);            return 1;        }else            return 0;    case LA_CONDITION_TRUE:        if (*IResult) *IResult = 1;        return 1;    case LA_CONDITION_FALSE:        if (*IResult) *IResult = 0;        return 0;    default:        Result1 = la_DoExpression(Expression->Expression1, &IValue1, &FValue1, &Str1, &Ptr1);        switch (Expression->Type){        case LA_CONDITION_AND:            if (Result1){                Result2 = la_DoExpression(Expression->Expression2, &IValue2, &FValue2, &Str2, &Ptr2);                if (Result2) *IResult = 1;                return (Result2);            }else                return 0;        case LA_CONDITION_OR:            if (!Result1){                Result2 = la_DoExpression(Expression->Expression2, &IValue2, &FValue2, &Str2, &Ptr2);                if (Result2) *IResult = 1;                return (Result2);            }else                return 1;        case LA_CONDITION_NOT:            return !Result1;        default:            Result2 = la_DoExpression(Expression->Expression2, &IValue2, &FValue2, &Str2, &Ptr2);            return la_DoCompare(Expression->Type,                                 (Expression->Expression1->Type == LA_CONDITION_PROP && Expression->Expression1->PP.LastPs) ? Expression->Expression1->PP.LastPs->p->PropertyType : Expression->Expression1->Type, IValue1, FValue1, Str1, Ptr1,                                 (Expression->Expression2->Type == LA_CONDITION_PROP && Expression->Expression2->PP.LastPs) ? Expression->Expression2->PP.LastPs->p->PropertyType : Expression->Expression2->Type, IValue2, FValue2, Str2, Ptr2);        }        break;    }    return 0;}int la_DoSingleExpression(laUiConditionNode *Expression){    int a;    real b;    char c[128]={0};    void *p;    if (!Expression) return 1;    c[0] = 0;    return la_DoExpression(Expression, &a, &b, c, &p);}void la_StepExpression(laUiConditionNode *e){    if (!e) return;    switch (e->Type){    case LA_CONDITION_AND:    case LA_CONDITION_OR:    case LA_CONDITION_GE:    case LA_CONDITION_GT:    case LA_CONDITION_EQ:    case LA_CONDITION_LT:    case LA_CONDITION_LE:        la_StepExpression(e->Expression1);        la_StepExpression(e->Expression2);        break;    case LA_CONDITION_NOT:        la_StepExpression(e->Expression1);        break;    case LA_CONDITION_PROP:        la_StepPropPack(&e->PP);        //if (e->PP.LastPs && e->PP.LastPs->p->Container && e->PP.LastPs->p->Container->Hyper){ // doesn't seem needed now with getuser            la_UsePropPack(&e->PP, 1);            //laUseDataBlock(e->PP.Go ? e->PP.LastPs->UseInstance : e->PP.EndInstance, e->PP.LastPs->p, MAIN.PropMatcherContextP->FrameDistinguish, MAIN.PropMatcherContextP, la_PropPanelUserRemover,1);        //}        break;    default:        break;    }}void la_ConditionNodeFreeRecursive(laUiConditionNode *ucn){    if (!ucn) return;    la_ConditionNodeFreeRecursive(ucn->Expression1);    la_ConditionNodeFreeRecursive(ucn->Expression2);    if (ucn->PP.LastPs) la_FreePropStepCache(ucn->PP.Go);    if (ucn->String) strSafeDestroy(&ucn->String);    if (ucn) memFree(ucn);}laUiItem *laOnConditionThat(laUiList *uil, laColumn *c, laUiConditionNode *Expression){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    ui->C = c;    ui->Type = &_LA_UI_CONDITION;    la_ConditionerInit(ui, Expression);    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laElse(laUiList *uil, laUiItem *Beginner){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    laConditionUiExtraData *cued;    ui->Type = &_LA_UI_CONDITION_ELSE;    la_ConditionerInit(ui, 0);    cued = ui->Extra;    cued->EndUi = Beginner;    ((laConditionUiExtraData *)Beginner->Extra)->ElseUi = ui;    ui->C = Beginner->C;    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laOnConditionToggle(laUiList *uil, laColumn *col, laUiDefineFunc define, int Remove, laPropPack *ExtraBase, laPropPack *ExtraThis, laWidget* Widget){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    laConditionUiExtraData *cued;    ui->Template = define;    ui->C = col;    ui->PP.RawThis = ExtraBase;    ui->Page = ExtraThis;    ui->Type = Widget? Widget->Type : _LA_UI_CONDITION_TOGGLE;    la_ConditionerInit(ui, 0);    cued = ui->Extra;    //cued->Remove = Remove;    ui->State = LA_UI_NORMAL;    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiItem *laEndCondition(laUiList *uil, laUiItem *Beginner){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    laConditionUiExtraData *cued;    ui->Type = &_LA_UI_CONDITION_END;    la_ConditionerInit(ui, 0);    cued = ui->Extra;    cued->EndUi = Beginner;    ((laConditionUiExtraData *)Beginner->Extra)->EndUi = ui;    ui->C = Beginner->C;    lstAppendItem(&uil->UiItems, ui);    return ui;}laUiList* laMakeMenuPage(laUiList* uil, laColumn* c, const char* Title) {    laUiItem* ui = memAcquireSimple(sizeof(laUiItem));    laUiList* muil = memAcquireSimple(sizeof(laUiList));    ui->Type = _LA_UI_MENU_ROOT;    strSafeSet(&ui->Display, Title);    ui->State = LA_UI_NORMAL; ui->Flags|=LA_TEXT_ALIGN_CENTER;    ui->C = c;    lstAppendItem(&uil->UiItems, ui);    lstAppendItem(&ui->Subs, muil);    return muil;}laUiItem *laShowSeparator(laUiList *uil, laColumn *widest){    laUiItem *ui = memAcquireSimple(sizeof(laUiItem));    ui->Type = _LA_UI_ALIGN;    ui->C = widest;    lstAppendItem(&uil->UiItems, ui);    return ui;}void laFixHeight(laUiList *uil, short Rows){    if (!uil) return;    uil->HeightCoeff = Rows;}void laMakeUiListFromTemplate(laUiList *Into, laUiDefineFunc Template,                               laPropPack *PanelPP, laPropPack *PanelExtraPP, laPropPack *Base, laPropPack *Operator, laListHandle *ExtraColumns, int Context){    if (!ExtraColumns) return;    Template(Into, Base, Operator, ExtraColumns->pFirst, Context);}laUiTemplate *laFindUiTemplate(char *Identifier){    laUiTemplate *uit;    for (uit = MAIN.PanelTemplates.pFirst; uit; uit = uit->Item.pNext){        if (!strcmp(uit->Identifier->Ptr, Identifier)) return uit;    }    for (uit = MAIN.InitPanelTemplates.pFirst; uit; uit = uit->Item.pNext){        if (!strcmp(uit->Identifier->Ptr, Identifier)) return uit;    }    return 0;}void la_DestroyUiTemplate(laUiTemplate* uit){    strSafeDestroy(&uit->Identifier);    strSafeDestroy(&uit->Title);    laKeyMapItem* kmi; while(kmi=lstPopItem(&uit->KeyMap.Items)){ la_FreeKeyMapItem(kmi); }    memFree(uit);}void la_DestroyCanvasTemplate(laCanvasTemplate* uit){    strSafeDestroy(&uit->Identifier);    laKeyMapItem* kmi; while(kmi=lstPopItem(&uit->KeyMapper.Items)){ la_FreeKeyMapItem(kmi); }    memFree(uit);}laUiTemplate *laRegisterUiTemplate(char *Identifier, char* Title, laUiDefineFunc func,laPanelDetachedPropFunc PropFunc, laUiDefineFunc header, char* NewCategory, int DefaultGLFormat, int DefaultW_RH, int DefaultH_RH){    laUiTemplate *uit = memAcquire(sizeof(laUiTemplate));    strSafeSet(&uit->Identifier, Identifier);    strSafeSet(&uit->Title, Title);    strSafeSet(&uit->CategoryName, NewCategory);    uit->Define = func; uit->Header = header; uit->PropFunc = PropFunc;    uit->DefaultGLFormat=DefaultGLFormat;    uit->DefaultH_RH=DefaultH_RH?abs(DefaultH_RH):15; uit->DefaultW_RH=DefaultW_RH?abs(DefaultW_RH):15;    if(MAIN.InitDone) lstAppendItem(&MAIN.PanelTemplates, uit); else lstAppendItem(&MAIN.InitPanelTemplates, uit);    la_UDFAppendSharedTypePointer(Identifier, uit);    return uit;}laCanvasTemplate *laRegisterCanvasTemplate(char *Identifier, char *ForContainer, laModalFunc ExtraModal, laCanvasDrawFunc Func, laUiDrawFunc SecondDraw, laUiInitFunc CustomInit, laUiDestroyFunc CustomDestroy){    laCanvasTemplate *t = memAcquire(sizeof(laCanvasTemplate));    strSafeSet(&t->Identifier, Identifier);    t->Draw = Func; t->SecondDraw = SecondDraw; t->TargetContainerID = ForContainer; t->ExtraModal=ExtraModal;    t->Init = CustomInit; t->Destroy = CustomDestroy;    lstAppendItem(&MAIN.View2DTemplates, t);    la_UDFAppendSharedTypePointer(Identifier, t);    return t;}void laFinalizeUiTemplates(){    laUiTemplate *uit;    laCanvasTemplate *u2d;    for (u2d = MAIN.View2DTemplates.pFirst; u2d; u2d = u2d->Item.pNext){        if (u2d->TargetContainerID) u2d->TargetContainer = la_ContainerLookup(u2d->TargetContainerID);    }}laPanel *la_FindFreePanelByTemplate(laWindow *w, const laUiTemplate *uit){    laPanel *p;    for (p=w->Panels.pFirst; p; p = p->Item.pNext){        if (p->PanelTemplate==uit){            return p;        }    }    return 0;}void la_DestroyUiItem(laUiItem *ui, int RemoveUsers){    laUiList *uil, *NextUil;    for (uil = ui->Subs.pFirst; uil; uil = NextUil){        NextUil = uil->Item.pNext;        lstRemoveItem(&ui->Subs, uil);        la_DestroyUiList(uil, 0, RemoveUsers, 0);    }    la_StopUiOperatorService(ui);    strSafeDestroy(&ui->ExtraInstructions);strDestroyStringSplitor(&ui->Instructions);    strSafeDestroy(&ui->Display);    //if (RemoveUsers && ui->PP.LastPs && ui->PP.LastPs->p->Container->Hyper)    //    { /*la_StopUsingPropPack(&ui->PP);*/ }        //laStopUsingDataBlock(ui->PP.LastPs->UseInstance,ui->PP.LastPs->p,MAIN.PropMatcherContextP);    la_FreePropStepCache(ui->PP.Go); //-------[Up Here], instance already been freed.XXXXXXXXXXXX!!!!!!!!!!1    if (ui->CompoundPPs.pFirst){laCompoundPP* CPP;        while(CPP = lstPopItem(&ui->CompoundPPs)){ la_FreePropStepCache(CPP->PP.Go); memFree(CPP); }    }    if (ui->Type->Destroy) ui->Type->Destroy(ui);    memFree(ui);}void la_DestroyUiList(laUiList *uil, int NoFree, int RemoveUsers, int OnlyRemoveUser){    laUiItem *ui, *NextUi;    laColumn *col, *NextCol;    if (!uil) return;    for (ui = uil->UiItems.pFirst; ui; ui = NextUi){        NextUi = ui->Item.pNext;        if(OnlyRemoveUser && RemoveUsers){            if (ui->PP.LastPs && ui->PP.LastPs->p->Container->Hyper)                { /*la_StopUsingPropPack(&ui->PP);*/ }                //laStopUsingDataBlock(ui->PP.LastPs->UseInstance,ui->PP.LastPs->p,MAIN.PropMatcherContextP);            continue;        }        lstRemoveItem(&uil->UiItems, ui);        la_DestroyUiItem(ui, RemoveUsers);    }    if(OnlyRemoveUser){ return; }    for (col = uil->Columns.pFirst; col; col = NextCol){        NextCol = col->Item.pNext;        lstRemoveItem(&uil->Columns, col);        memFree(col);    }    strSafeDestroy(&uil->TabName);    if (!NoFree) memFree(uil);}void la_DestroyTabPage(laUiItem *ui, laUiList *Tab, int RemoveUsers){    if(ui) lstRemoveItem(&ui->Subs, Tab);    la_DestroyUiList(Tab, 1, RemoveUsers, 0);}void la_CreateUiAfter(laUiList *uil, laUiItem *after, laUiDefineFunc Define, laPropPack *Base, laPropPack *This, laColumn **ExtraColums){    laUiItem *Next = after->Item.pNext;    laUiItem *Last = uil->UiItems.pLast;    after->Item.pNext = 0;    uil->UiItems.pLast = after;    Define(uil, Base, This, ExtraColums, 0);    if (Next) Next->Item.pPrev = uil->UiItems.pLast;    ((laUiItem *)uil->UiItems.pLast)->Item.pNext = Next;    if (Next != Last) uil->UiItems.pLast = Last;}//void la_RefreshExtraColumns(laUiItem* ui, int B,int FromL,int ToL,int FromR,int ToR){//	int i = 0;//	int FromW=FromR-FromL, ToW=ToR-ToL;//	if (!ui->ExtraColums) return;//	for (i; ui->ExtraColums[i]; i++) {//		laColumn* c = ui->ExtraColums[i];//		c->B = B;//		c->IL = (c->IL - FromL) / FromW*ToW + ToL;//		c->IR = (c->IR - FromL) / FromW*ToW + ToL;//	}//}void la_PropPanelUserRemover(void* this_UNUSED, laItemUserLinker* iul){    laPanel* p = iul->Pointer.p; if(p->FrameDistinguish == iul->FrameDistinguish){ laRecalcPanel(p); }}void la_CalcUiItemInfluence(laListHandle *lst, laUiItem *ui){    laColumn *c = ui->C;    laColumn *ic = lst->pFirst;    c->B = ui->TB + (*ui->Type->Theme)->BP;    for (ic; ic; ic = ic->Item.pNext){        if (((ic->IR > c->IL) && (ic->IL < c->IR)) || ((ic->IL < c->IR) && (ic->IR > c->IL))){            ic->B = ic->B < c->B ? c->B : ic->B;        }    }    ic = ui->C;    while (ic->Item.pPrev && (ic = ic->Item.pPrev))        ;    for (ic; ic; ic = ic->Item.pNext){        if (((ic->IR > c->IL) && (ic->IL < c->IR)) || ((ic->IL < c->IR) && (ic->IR > c->IL))){            ic->B = ic->B < c->B ? c->B : ic->B;        }    }}void la_CalcUiTopInfluence(laListHandle *lst, laUiItem *ui){    laColumn *c = ui->C;    laColumn *ic = lst->pFirst;    c->B = ui->TB + (*ui->Type->Theme)->TP;    for (ic; ic; ic = ic->Item.pNext){        if (((ic->IR > c->IL) && (ic->IL < c->IR)) || ((ic->IL < c->IR) && (ic->IR > c->IL))){            ic->B = ic->B < c->B ? c->B : ic->B;        }    }    ic = ui->C;    while (ic->Item.pPrev && (ic = ic->Item.pPrev))        ;    for (ic; ic; ic = ic->Item.pNext){        if (((ic->IR > c->IL) && (ic->IL < c->IR)) || ((ic->IL < c->IR) && (ic->IR > c->IL))){            ic->B = ic->B < c->B ? c->B : ic->B;        }    }}int la_ResetUiColum(laColumn *c, laColumn *Top, int U, int L, int R, int LR, int repos){ //1=L,2=R    int rep;    int sp;    int rev;    int M=_LA_THEME_PANEL->LM+_LA_THEME_PANEL->RM;    if (!c) return 0;    sp = (c->SP * (R - L)) + L;    rev = sp;    /*if (U)*/ c->B = U;    if (LR == 1){        c->IL = L;        c->IR = sp;        if (repos){            c->IR = repos;        }else if (c->MaxW*LA_RH && c->IR - c->IL > c->MaxW*LA_RH+M){            c->IR = c->IL + c->MaxW*LA_RH+M;            rev = c->IR;        }    }else if (LR == 2){        c->IL = sp;        c->IR = R;        if (repos){            c->IL = repos;        }else if (c->MaxW*LA_RH && c->IR - c->IL > c->MaxW*LA_RH+M){            c->IL = c->IR - c->MaxW*LA_RH-M;            rev = c->IL;        }    }else if (LR == 0){        c->IL = L;        c->IR = R;    }    if (c->LS && c->RS->MaxW == 0){        rep = la_ResetUiColum(c->LS, Top, U, c->IL, c->IR, 1, 0);        la_ResetUiColum(c->RS, Top, U, c->IL, c->IR, 2, rep);        c->LS->PreWidth = c->PreWidth * c->LS->SP;        c->RS->PreWidth = c->PreWidth * (1 - c->RS->SP);    }else if (c->RS && c->LS->MaxW == 0){        rep = la_ResetUiColum(c->RS, Top, U, c->IL, c->IR, 2, 0);        la_ResetUiColum(c->LS, Top, U, c->IL, c->IR, 1, rep);        c->LS->PreWidth = c->PreWidth * c->LS->SP;        c->RS->PreWidth = c->PreWidth * (1 - c->RS->SP);    }    return rev;}STRUCTURE(laRowInfo){    int MaxW;    int MinW;    int UnitMinW;    int NonExpandW;    int TotalPadding;    int Expand, Even;    int ExpandAccum;    int CountElements;    int U,MaxB,L;    laListHandle Elements;    int LastNoHeight;};STRUCTURE(laRowNode){    laListItem Item;    laUiItem* ui;    int GotW, LP, RP, H;    int Expand;    int UseLast;};int la_InitRowNode(laRowInfo* ri, laUiItem* ui, laBoxedTheme* bt){    ri->MaxW = ui->TR-ui->TL;//row node does not use margin    ri->UnitMinW=LA_RH;    ri->Expand=ui->State?1:0;    ri->Even=ui->Flags?1:0;    ri->U=ui->TU; ri->L=ui->TL;    ri->MaxB=ui->TU;}void la_AddRowNode(laRowInfo* ri, laUiItem* ui, laBoxedTheme* bt, int H){    laRowNode* rn=CreateNew(laRowNode);    rn->LP=bt->LP;rn->RP=bt->RP;    rn->GotW = (ui->Type->GetMinWidth?ui->Type->GetMinWidth(ui):(LA_RH));    rn->ui=ui;    rn->H=H;    rn->Expand=ui->Expand;    lstAppendItem(&ri->Elements, rn);    if(ri->LastNoHeight){ ri->LastNoHeight=0; rn->UseLast=1; return; }    if(ui->Flags&LA_UI_FLAGS_UNDERNEATH){ ri->LastNoHeight=1; };    if(!ri->UnitMinW){ri->UnitMinW=LA_RH;}    ri->TotalPadding += (bt->LP+bt->RP);    ri->MinW+=ri->UnitMinW;    ri->NonExpandW+=rn->GotW;    ri->ExpandAccum+=ui->Expand;    ri->CountElements++;    if(ui->Expand){ri->Expand=1;}    if(ri->U+H+bt->BP>ri->MaxB){ri->MaxB=ri->U+H+bt->BP;}}int la_ShrinkableRowElements(laRowInfo* ri){    int count=0;    for(laRowNode* rn=ri->Elements.pFirst;rn;rn=rn->Item.pNext){        if(rn->GotW<=ri->UnitMinW || rn->UseLast) continue;        count++;    }    return count;}void la_RecordSocketRuntimePosition(laUiItem* ui);int la_CalculateRowExpand(laRowInfo* ri, laUiItem* ui_end, int WaitAnimation){    int Available=ri->MaxW-ri->NonExpandW-ri->TotalPadding;    int ShareCount=0, Additional=0, AdditionalRemaining=0, Shrinkable=0; real NodeAddFraction=0;    if(Available<0){        ShareCount=1;// Shrinkable=la_ShrinkableRowElements(ri);        Additional=(ri->MaxW-ri->MinW-ri->TotalPadding)/ri->CountElements;        AdditionalRemaining = (ri->MaxW-ri->MinW-ri->TotalPadding)-Additional*ri->CountElements;    }else{        if(!ri->Expand && Available>0){Available=0;}        ShareCount=ri->ExpandAccum?ri->ExpandAccum:ri->CountElements;    }    if(!ShareCount) return 0;    int PerNode = Available/ShareCount;    int Remaining = Available-PerNode*ShareCount;    int L = ri->L; int i=0; laRowNode* rn;    for(rn=ri->Elements.pFirst;rn;rn=rn->Item.pNext){        laUiItem* ui=rn->ui;        int NodeAdd, Node=rn->GotW;        if(rn->UseLast){            laRowNode* prevrn=rn->Item.pPrev; laUiItem* prevui=prevrn->ui;            rn->ui->TL=prevui->TL;rn->ui->TR=prevui->TR;rn->ui->TU=prevui->TU;rn->ui->TB=prevui->TB;            continue;        }        if(Available>=0){            NodeAdd=ri->ExpandAccum?(PerNode*rn->Expand):PerNode;            NodeAdd+=(i<Remaining?1:0);i++;        }else{            if(ri->MaxW>=ri->MinW+ri->TotalPadding) {                NodeAddFraction+=((rn->GotW>ri->UnitMinW)?(real)Available*(real)(rn->GotW-ri->UnitMinW)/(real)(ri->NonExpandW-ri->MinW):0);                NodeAdd=(int)NodeAddFraction; NodeAddFraction-=NodeAdd;            }else{ Node=ri->UnitMinW;                NodeAdd=Additional+(i<-AdditionalRemaining?-1:0);i++;            }        }        ui->TL = L + rn->LP;        ui->TR = ui->TL + Node+NodeAdd;        ui->TB = ui->TU + rn->H;        L=ui->TR+rn->RP;        if (!WaitAnimation){            ui->L = ui->TL; ui->R = ui->TR;            ui->U = ui->TU; ui->B = ui->TB;        }        if(ui->Type==_LA_UI_NODE_SOCKET){ la_RecordSocketRuntimePosition(ui); }    }    ui_end->TB = ui_end->Flags&LA_UI_FLAGS_UNDERNEATH?ri->U:ri->MaxB;    while(rn=lstPopItem(&ri->Elements)){ FreeMem(rn); }    memset(ri, 0, sizeof(laRowInfo));}void la_RecordSocketRuntimePosition(laUiItem* ui){    laProp* p=ui->PP.LastPs->p; laPropContainer* pc=la_EnsureSubTarget(p,0);    int sl,sr,su,sb;    if(ui->Flags&LA_UI_SOCKET_LABEL_N){ sl=ui->TL; sr=ui->TR; su=ui->TU+LA_RH; }    elif(ui->Flags&LA_UI_SOCKET_LABEL_S){ sl=ui->TL; sr=ui->TR; su=ui->TU; }    elif(ui->Flags&LA_UI_SOCKET_LABEL_W){ sl=ui->TL+LA_2RH; sr=ui->TR; su=ui->TU; }    elif(ui->Flags&LA_UI_SOCKET_LABEL_E){ sl=ui->TL; sr=ui->TR-LA_2RH; su=ui->TU; }    else{ sl=ui->TL; su=ui->TU; sr=ui->TR; } sb=su+LA_RH;     if(pc==LA_PC_SOCKET_OUT){        laNodeOutSocket* s=ui->PP.EndInstance; s->RuntimeX=(sl+sr)/2; s->RuntimeY=(su+sb)/2;    }else{        laNodeInSocket* s=ui->PP.EndInstance;  s->RuntimeX=(sl+sr)/2; s->RuntimeY=(su+sb)/2;        laUseDataBlock(s, LA_PROP_SOCKET_SOURCE, MAIN.PropMatcherContextP->FrameDistinguish, MAIN.PropMatcherContextP, la_PropPanelUserRemover, 0);    }}laUiList* la_GiveExistingPage(laListHandle* from, void* instance){    for(laUiList* uil=from->pFirst;uil;uil=uil->Item.pNext){ if(uil->Instance == instance){ lstRemoveItem(from,uil); return uil; } } return 0;}void la_SwitchThemeQuick(laTheme* t, laTheme* DefaultTheme);int la_UpdateUiListRecursive(laUiList *uil, int U, int L, int R, int B, int Fast, laPanel *ParentPanel){    laUiItem *ui; laListHandle TempPages={0}; laUiList* FoundUil;    laBoxedTheme *bt;    int Lowest = 0;    int HyperValue = 0;    int WaitAnimation;    int RowMode=0; laRowInfo ri={0};    laBoxedTheme* pt=*(ParentPanel->BT);    int _PL=-pt->LM,_PR=-pt->RM,_PT=-pt->TM,_PB=-pt->BM;    int MaxR=0;    if(!uil->Scale){uil->Scale=1;}    uil->SaveScale=MAIN.UiScale;    MAIN.UiScale*=uil->Scale;    MAIN.ScaledUiRowHeight=MAIN.UiRowHeight*MAIN.UiScale;    uil->TU = U;uil->TL = L;uil->TR = R;uil->TB = uil->TU;    WaitAnimation = 0;    if (!uil->Columns.pFirst && !uil->UiItems.pFirst) return U;    la_ResetUiColum(uil->Columns.pFirst, uil->Columns.pFirst, U, L, R, 0, 0);    for (ui = uil->UiItems.pFirst; ui;){        int SubB = 0;        int H;        WaitAnimation = 0;        int NoGap=ui->Flags&LA_UI_FLAGS_NO_GAP;        int NoHeight=ui->Flags&LA_UI_FLAGS_UNDERNEATH;        //if (Fast && ui->C->B > B) {        //	//la_CalcUiItemInfluence(&uil->Colums, ui);        //	ui = ui->Item.pNext;        //	continue;        //}        if (!ui->Instructions){            if (ui->ExtraInstructions) strMakeInstructions(&ui->Instructions, ui->ExtraInstructions->Ptr);            if (ui->AT && ui->AT->ExtraInstructions) strMakeInstructions(&ui->Instructions, ui->AT->ExtraInstructions);            if (ui->PP.LastPs && ui->PP.LastPs->p->PropertyType == LA_PROP_OPERATOR){                laOperatorProp *ap = ui->PP.LastPs->p;                if (!ap->OperatorType) ap->OperatorType = laGetOperatorType(ap->OperatorID);                if (ap->OperatorType&&ap->OperatorType->ExtraInstructions) strMakeInstructions(&ui->Instructions, ap->OperatorType->ExtraInstructions);            }        }        if (ui->PP.LastPs){ la_StepPropPack(&ui->PP); }        la_UsePropPack(&ui->PP, 0);        if (ui->CompoundPPs.pFirst){            for(laCompoundPP* CPP=ui->CompoundPPs.pFirst;CPP;CPP=CPP->Item.pNext){                la_StepPropPack(&CPP->PP); la_UsePropPack(&CPP->PP, 0);            }        }        if(ui->Type==&_LA_UI_INVISIBLE){ ui=ui->Item.pNext; continue; }        //if (ui->PP.LastPs && (HyperValue = ui->PP.LastPs->p->Container ? ui->PP.LastPs->p->Container->Hyper : 0)){        //    laUseDataBlock(ui->PP.Go ? ui->PP.LastPs->UseInstance : ui->PP.RawThis->LastPs->UseInstance, ui->PP.LastPs->p, MAIN.PropMatcherContextP->FrameDistinguish, MAIN.PropMatcherContextP, la_PropPanelUserRemover, 0);        //}        if ((ui->AnimationDistinguish + 1) == ParentPanel->FrameDistinguish){            ParentPanel->Refresh |= LA_TAG_ANIMATION; laRefreshWindow();            WaitAnimation = 1;        }        ui->AnimationDistinguish = ParentPanel->FrameDistinguish;        bt = (*ui->Type->Theme);        if (ui->Type == &_LA_UI_CONDITION){            laConditionUiExtraData *cued = ui->Extra;            la_StepExpression(cued->Expression);            cued->IsTrue = la_DoSingleExpression(cued->Expression);            if (!cued->IsTrue){                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                ui = ui->Item.pNext;            }            continue;        }else if (ui->Type == &_LA_UI_CONDITION_END){            ui = ui->Item.pNext;            continue;        }else if (ui->Type == &_LA_UI_CONDITION_ELSE){            laConditionUiExtraData *cued = ((laConditionUiExtraData *)ui->Extra)->EndUi->Extra;            if (cued->IsTrue) ui = cued->EndUi;            else                ui = ui->Item.pNext;            continue;        }else if (ui->Type == _LA_UI_CONDITION_TOGGLE){            laConditionUiExtraData *cued = ui->Extra;            ui->TL = ui->C->IL + bt->LP; ui->TR = ui->C->IR - bt->RP;            ui->TU = ui->C->B + bt->TP;  ui->TB = ui->TU+LA_RH;            if (!WaitAnimation){                ui->L = ui->TL; ui->R = ui->TR;                ui->U = ui->TU; ui->B = ui->TB;            }            if(!RowMode){                la_CalcUiItemInfluence(&uil->Columns, ui);            }else{                H = ui->Type->GetHeight ? ui->Type->GetHeight(ui) : 1;                la_AddRowNode(&ri, ui, bt, H*LA_RH);            }            if (ui->State == LA_UI_NORMAL){                cued->IsTrue = 0;                //if(cued->Remove && (ui->Item.pNext != cued->EndUi))                //	la_DestroyUiRange(uil, ui->Item.pNext, cued->ElseUi?cued->ElseUi->Item.pPrev:cued->EndUi->Item.pPrev);                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                cued->IsTrue = 1;                //if (cued->Remove && (ui->Item.pNext == cued->EndUi || ui->Item.pNext==cued->ElseUi)) {                //	la_CreateUiAfter(uil, ui, ui->Template, ui->PP.RawThis, ui->Page, uil->Columns.pFirst);                //}                ui = ui->Item.pNext;            }            continue;        }        if (ui->Type == _LA_UI_ALIGN){            ui->TU = ui->C->B + bt->TP; ui->TB = ui->TU+LA_RH/5;            ui->TL = ui->C->IL; ui->TR = ui->C->IR;            if (ui->TB > Lowest) Lowest = ui->TB;            if (!WaitAnimation){                ui->L = ui->TL; ui->R = ui->TR;                ui->U = ui->TU; ui->B = ui->TB;            }            if(!RowMode){                la_CalcUiItemInfluence(&uil->Columns, ui);            }else{                ui->Flags|=LA_UI_FLAGS_TRANSPOSE;                H = ui->Type->GetHeight ? ui->Type->GetHeight(ui) : 1;                la_AddRowNode(&ri, ui, bt, H*LA_RH);            }            ui = ui->Item.pNext; continue;        }        if (ui->Type == &_LA_UI_ROW_BEGIN){            ui->TU = ui->C->B; ui->TL = ui->C->IL; ui->TR = ui->C->IR;            la_InitRowNode(&ri, ui, bt);            RowMode=1; ui=ui->Item.pNext; continue;        }        if (ui->Type == &_LA_UI_ROW_END){            la_CalculateRowExpand(&ri, ui, WaitAnimation);            la_CalcUiItemInfluence(&uil->Columns, ui);            RowMode=0; ui=ui->Item.pNext; continue;        }        if(!RowMode){ ui->TL = ui->C->IL + (NoGap?_PL:bt->LP); ui->TR = ui->C->IR - (NoGap?_PR:bt->RP); }        int GB=0;        if (ui->Type == _LA_UI_FIXED_GROUP && ui->Page->HeightCoeff < 0 && ui->Flags&LA_UI_FLAGS_PREFER_BOTTOM){ GB=ui->Page->TB-ui->Page->PanY; }        H = ui->Type->GetHeight ? ui->Type->GetHeight(ui) : 1;        ui->TU = ui->C->B + (NoGap?_PT:bt->TP);        if (H < 0){            if(B){ H = B + (H+1) * LA_RH - ui->TU+_PB+((H<-1)?_PT:0); }            else{ H=LA_RH; }        }         else H *= LA_RH;        ui->TB = ui->TU;                int NoDecal=ui->Flags&LA_UI_FLAGS_NO_DECAL;        if (ui->Type->ForType == LA_PROP_SUB && ui->PP.LastPs && ui->PP.LastPs->p && ui->PP.LastPs->p->PropertyType == LA_PROP_SUB && ui->Type != _LA_UI_CANVAS){ //DynamicCreation            laPropIterator pi = {0}; laSubProp* uisp=ui->PP.LastPs->p;            if (ui->Type == _LA_UI_COLLECTION){                //void* TInstance = ui->PP.Go?laGetInstance(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, &pi):ui->PP.EndInstance;                void *TInstance = laGetInstance(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, &pi);                ui->PP.EndInstance = TInstance;                laUiList *iuil = ui->Subs.pFirst;                 laUiList *puil = iuil;                int Row = 0, Col = 0, RowPriority = ui->SymbolID > 0 ? 1 : 0, ElementLimit = ui->SymbolID ? abs(ui->SymbolID) : 0;                int Spread=ui->Expand>2?ui->Expand:0; if(Spread){ RowPriority=0; ElementLimit=0; }                laUiDefineFunc Template = ui->Template ? ui->Template : laGetPropertyUiDefine(&ui->PP, TInstance);                int Begin = ui->TB;                int EL = ui->TL, ER = Spread?(Spread*LA_RH+ui->TL):ui->TR;                int ElementB = ui->TU;                real ElementWidth = ElementLimit ? 1.0f / ElementLimit : 1.0;                int MaxB = ElementB;                int CanGetTheme = laCanGetTheme(ui->PP.LastPs->p);laTheme* OriginalTheme=MAIN.CurrentTheme;                int CanGetGap= laCanGetGap(ui->PP.LastPs->p); int Gap=0;                int CanGetCategory= laCanGetCategory(ui->PP.LastPs->p); char _cat[256]; char* cat=_cat; int GotCategory=0,FirstIn=1;                if (!ElementLimit) RowPriority = 0;                if (!TInstance){                    while (iuil){                        puil = iuil->Item.pNext;                        la_DestroyTabPage(ui, iuil, 0);                        iuil = puil;                    }                }                while (TInstance){                    if(uisp->UiFilter && (!uisp->UiFilter(ui->PP.LastPs->UseInstance, TInstance))){                        TInstance = laGetNextInstance(ui->PP.LastPs->p, TInstance, &pi);                        Template = ui->Template?ui->Template:laGetPropertyUiDefine(&ui->PP, TInstance);                        ui->PP.EndInstance = TInstance; continue;                    }                    if(CanGetTheme){                        laTheme* t=laGetUiTheme(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, ui->PP.EndInstance);                        la_SwitchThemeQuick(t, OriginalTheme);                    }                    if(CanGetGap){                        int g=laGetUiGap(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, ui->PP.EndInstance); g=g<0?0:g;                        Gap=g*LA_RH;                    }else Gap=0;                    if(CanGetCategory){ _cat[0]=0; cat=_cat; GotCategory=0;                        laGetCategory(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, ui->PP.EndInstance, _cat, &cat); if(cat[0]) GotCategory=1;                    }else GotCategory=0;                    if(GotCategory){ Begin+=LA_RH*(FirstIn?1:1.5)+bt->TM;                         if (RowPriority){                            Row += 1; Col=0; Begin = ElementB+bt->TM+LA_RH*(FirstIn?1:1.5)+bt->TM;                        }                    }                    FirstIn=0;                    if (ElementLimit){                        EL = tnsInterpolate(ui->TL, ui->TR, (Col)*ElementWidth);                        ER = tnsInterpolate(ui->TL, ui->TR, (Col + 1) * ElementWidth);                    }                    while (iuil && iuil->Instance != TInstance){                        if(FoundUil=la_GiveExistingPage(&TempPages, TInstance)){                            lstInsertItemBefore(&ui->Subs, FoundUil, iuil); puil = FoundUil;                        }else{                            puil = iuil->Item.pNext; lstRemoveItem(&ui->Subs, iuil); lstAppendItem(&TempPages, iuil);                        }                        iuil = puil;                    }                    if(!iuil){                        if(FoundUil=la_GiveExistingPage(&TempPages, TInstance)){ lstAppendItem(&ui->Subs, FoundUil); iuil = FoundUil; }                    }                    if (!iuil){                            la_AddInstancePage(ui, TInstance, 0); if(GotCategory){ strSafeSet(&ui->Page->TabName,cat); }                            la_CalcUiTopInfluence(&uil->Columns, ui);                            if (Template) laMakeUiListFromTemplate(ui->Page, Template, &ParentPanel->PP, &ParentPanel->PropLinkPP, &ui->PP, 0, &uil->Columns, ui->TemplateContext);                            SubB = la_UpdateUiListRecursive(ui->Page, Gap+Begin+(NoDecal?0:bt->TM), EL+(NoDecal?0:bt->LM), ER-(NoDecal?0:bt->RM), B, Fast, ParentPanel) +(NoDecal?0:bt->TM);                            ElementB = RowPriority ? (SubB > ElementB ? SubB : ElementB) : SubB;                            iuil = ui->Page->Item.pNext;                    }else{                        la_CalcUiTopInfluence(&uil->Columns, ui); if(GotCategory){ strSafeSet(&iuil->TabName,cat); }                        SubB = la_UpdateUiListRecursive(iuil, Gap+Begin+(NoDecal?0:bt->TM), EL+(NoDecal?0:bt->LM), ER-(NoDecal?0:bt->RM), B, Fast, ParentPanel) + (NoDecal?0:bt->TM);                        ElementB = RowPriority ? (SubB > ElementB ? SubB : ElementB) : SubB;                        la_CalcUiItemInfluence(&uil->Columns, ui);                        iuil = iuil->Item.pNext;                    }                    TInstance = laGetNextInstance(ui->PP.LastPs->p, TInstance, &pi);                    Template = ui->Template?ui->Template:laGetPropertyUiDefine(&ui->PP, TInstance);                    ui->PP.EndInstance = TInstance;                                        if(CanGetTheme){ la_SwitchThemeQuick(0, OriginalTheme); }                    if (RowPriority){                        Col += 1;                        if (Col >= ElementLimit){                            Col = 0;                            Row += 1;                            Begin = ElementB + bt->TM;                        }                    }elif(Spread){                        EL+=Spread*LA_RH;                        ER+=Spread*LA_RH;                    }else{                        Row += 1;                        Begin = ElementB + bt->TM;                        if (ElementLimit && Row >= ElementLimit){                            Row = 0;                            Col += 1;                            Begin = ui->TU + bt->TM;                        }                    }                    ui->TB = ElementB;                    MaxB = MaxB < ElementB ? ElementB : MaxB;                }                while (iuil){ puil = iuil->Item.pNext; la_DestroyTabPage(ui, iuil, 0); iuil = puil; }                while (iuil=lstPopItem(&TempPages)){ la_DestroyTabPage(0, iuil, 0); }                ui->PP.EndInstance = laGetActiveInstance(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, &pi);                ui->TB = MaxB;                if(Spread){ ui->TR=ER-Spread*LA_RH; if(ui->TR>MaxR) MaxR=ui->TR; }                if (!WaitAnimation){ ui->L = ui->TL; ui->R = ui->TR; ui->U = ui->TU; ui->B = ui->TB = MaxB; }            }else if (ui->Type == _LA_UI_COLLECTION_SELECTOR || ui->Type == _LA_UI_COLLECTION_SINGLE){                if(ui->Flags&LA_UI_COLLECTION_SIMPLE_SELECTOR){                    ui->TB=ui->TU+LA_RH;                }else{                    void *TInstance = laGetActiveInstanceStrict(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance);                    ui->PP.EndInstance = TInstance;                    laUiTemplate *Template = ui->Template ? ui->Template : laGetPropertyUiDefine(&ui->PP, TInstance);                    if(!Template) Template=laui_SubPropInfoDefault;                    //ui->Template = Template;                    int EraseWidth=(ui->Type == _LA_UI_COLLECTION_SELECTOR)?LA_RH:0;                    if (!ui->Subs.pFirst && TInstance){                        la_AddInstancePage(ui, TInstance, 0);                        la_CalcUiTopInfluence(&uil->Columns, ui);                        laMakeUiListFromTemplate(ui->Page, Template, &ParentPanel->PP, &ParentPanel->PropLinkPP, &ui->PP, 0, &uil->Columns, ui->TemplateContext);                        SubB = la_UpdateUiListRecursive(ui->Page, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-EraseWidth, B, Fast, ParentPanel);                        ui->TB = SubB + (NoDecal?0:bt->BM);                    }else if (ui->Subs.pFirst){                        if (!TInstance || TInstance != ui->Page->Instance){                            la_DestroyTabPage(ui, ui->Subs.pFirst, 0);                            ui->Page = 0;                            if (TInstance){                                la_AddInstancePage(ui, TInstance, 0);                                la_CalcUiTopInfluence(&uil->Columns, ui);                                laMakeUiListFromTemplate(ui->Page, Template, &ParentPanel->PP, &ParentPanel->PropLinkPP, &ui->PP, 0, &uil->Columns, ui->TemplateContext);                                SubB = la_UpdateUiListRecursive(ui->Page, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-EraseWidth, B, Fast, ParentPanel);                                ui->TB = SubB + (NoDecal?0:bt->TM);                            }else                                ui->TB = ui->TU + LA_RH + bt->BM;                        }else{                            SubB = la_UpdateUiListRecursive(ui->Page, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-EraseWidth, B, Fast, ParentPanel);                            ui->TB = SubB + (NoDecal?0:bt->BM);                        }                    }                    if(ui->Type == _LA_UI_COLLECTION_SELECTOR && (ui->TB>(ui->TU+LA_RH*0.9))&&(ui->TB<ui->TU+(LA_RH*1.1))){                        ui->TB=ui->TU+LA_RH;                    }                }                if (ui->TB-ui->TU<LA_RH) ui->TB = ui->TU + LA_RH;                if (!WaitAnimation){                    ui->L = ui->TL;                    ui->R = ui->TR;                    ui->U = ui->TU;                    ui->B = ui->TB;                }            }        }else{            if (ui->Type != _LA_UI_COLLECTION && (ui->Subs.pFirst || ui->Page) && ui->Type != _LA_UI_MENU_ROOT){                if (ui->Type != _LA_UI_CANVAS){                    int scrollw=ui->Page->ScrollerShownV?bt->RP*2+LA_SCROLL_W:0;                    la_CalcUiTopInfluence(&uil->Columns, ui); int first_in=((ui->Flags&LA_UI_FLAGS_PREFER_BOTTOM) && ui->Page->B==0);                    SubB = la_UpdateUiListRecursive(ui->Page,                        ui->TB + (ui->State == LA_UI_ACTIVE ? 0 : LA_RH)+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-scrollw, B, Fast, ParentPanel);                    ui->TB = (ui->Page->HeightCoeff > 0 ? ui->TU + ui->Page->HeightCoeff * LA_RH :                            (ui->Page->HeightCoeff < 0 ? B + (ui->Page->HeightCoeff+1) * LA_RH + (_PB+_PT)+(ui->Page->HeightCoeff==-2?_PB:0) : SubB)) + (NoDecal?0:bt->BM);                    int subh = ui->TB-ui->TU-LA_RH-bt->TM-bt->BM;                    if((ui->Page->TR>ui->TR-(NoDecal?0:bt->RM) && (!ui->Page->ScrollerShownH)) ||                        (ui->Page->TR<=ui->TR-(NoDecal?0:bt->RM)  && ui->Page->ScrollerShownH)){                        ui->Page->ScrollerShownH=!ui->Page->ScrollerShownH;                    }                    if(ui->Page->AllowScale){ui->Page->ScrollerShownH=1;}                    if(ui->Page->ScrollerShownH){subh-=LA_SCROLL_W-bt->BM;}                    if((GB && ui->TB >= GB)||first_in){ ui->Page->PanY=(SubB-ui->TB-bt->BM); if(ui->Page->PanY<0)ui->Page->PanY=0; }                    if(ui->Page->HeightCoeff){                        if((subh<ui->Page->TB-ui->Page->TU && (!ui->Page->ScrollerShownV)) ||                            (subh>=ui->Page->TB-ui->Page->TU && ui->Page->ScrollerShownV)){                            ui->Page->ScrollerShownV=!ui->Page->ScrollerShownV;                            ParentPanel->Refresh|=LA_TAG_RECALC_SCROLLER;  laRefreshWindow();                        }                        if(SubB-ui->Page->PanY<ui->TB-bt->BM-(ui->Page->ScrollerShownH?LA_SCROLL_W+bt->BM:0)){                            ui->Page->PanY = (SubB-ui->TB-bt->BM+(ui->Page->ScrollerShownH?LA_SCROLL_W+bt->BM:0));                            if(ui->Page->PanY<0){ui->Page->PanY=0;}                            //ParentPanel->Refresh|=LA_TAG_RECALC_SCROLLER;                        }                    }                    if(ui->Page->ScrollerShownH && !ui->Page->HeightCoeff){                        ui->TB+=(bt->BP*2+LA_SCROLL_W); }                }else{                    laUiList *suil;                    if(!MAIN.CurrentWindow->MaximizedUi || ui!=MAIN.CurrentWindow->MaximizedUi){                        la_CalcUiTopInfluence(&uil->Columns, ui);                        for (suil = ui->Subs.pFirst; suil; suil = suil->Item.pNext){                            SubB = la_UpdateUiListRecursive(suil, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM), ui->TU+H, Fast, ParentPanel);                        }                    }                    ui->TB = ui->TU + H;                }            }else ui->TB = ui->TU + H;        }        if (ui->TB > Lowest && (!NoHeight)) Lowest = ui->TB + (bt ? (NoGap?_PB:bt->BP) : 0);        if(!RowMode){            if(!NoHeight) la_CalcUiItemInfluence(&uil->Columns, ui);        }else{            la_AddRowNode(&ri, ui, bt, H);        }        if (!WaitAnimation){ ui->L = ui->TL; ui->R = ui->TR; ui->U = ui->TU; ui->B = ui->TB; }        if(ui->Type==_LA_UI_NODE_SOCKET){  la_RecordSocketRuntimePosition(ui); }        ui = ui->Item.pNext;    }    uil->TR=MaxR>uil->TR?MaxR:uil->TR;    if (uil->Columns.pFirst) uil->TB = ((laColumn *)uil->Columns.pFirst)->B;    else uil->TB = Lowest;    if (!WaitAnimation){        uil->L = uil->TL;        uil->R = uil->TR;        uil->U = uil->TU;        uil->B = uil->TB;    }    MAIN.UiScale=uil->SaveScale;    MAIN.ScaledUiRowHeight=MAIN.UiRowHeight*MAIN.UiScale;    return uil->TB;}int la_AnimateSingleUiSize(int To, int *Now){    int Delta;    if (To != *Now){        Delta = (To - (*Now)) * (MAIN.AnimationSpeed) * MAIN.LastFrameTime * 60;        if (!Delta) Delta = To > (*Now) ? 1 : -1;        *Now += Delta;        return 1;    }else        return 0;}int la_AnimateUiListRecursive(laUiList *uil){    laUiItem *ui;    int Again = 0;    for (ui = uil->UiItems.pFirst; ui; ui = ui->Item.pNext){        int TB = ui->B, TU = ui->U, TL = ui->L, TR = ui->R, SB, SU, SL, SR;        Again += (la_AnimateSingleUiSize(ui->TB, &ui->B) +                  la_AnimateSingleUiSize(ui->TU, &ui->U) +                  la_AnimateSingleUiSize(ui->TL, &ui->L) +                  la_AnimateSingleUiSize(ui->TR, &ui->R));        if (ui->Type == _LA_UI_COLLECTION_SELECTOR || ui->Type == _LA_UI_COLLECTION_SINGLE ||            (ui->PP.LastPs && ui->PP.LastPs->p && ui->PP.LastPs->p->PropertyType == LA_PROP_SUB && ui->Type != _LA_UI_CANVAS)){            laUiList *suil;            for (suil = ui->Subs.pFirst; suil; suil = suil->Item.pNext){                Again += la_AnimateUiListRecursive(suil);            }        }else if (ui->Type != _LA_UI_COLLECTION && ui->Type != &_LA_UI_ROW_END &&                 (ui->Subs.pFirst || ui->Page) && ui->Type != _LA_UI_MENU_ROOT){            Again += la_AnimateUiListRecursive(ui->Page);        }    }    Again += (la_AnimateSingleUiSize(uil->TB, &uil->B) +              la_AnimateSingleUiSize(uil->TU, &uil->U) +              la_AnimateSingleUiSize(uil->TL, &uil->L) +              la_AnimateSingleUiSize(uil->TR, &uil->R));    return Again;}int la_DrawUiItem(laUiItem *ui){    tnsUseNoTexture();    tnsColor4d(1, 1, 1, 1);    tnsVertex2d(ui->L, ui->U);    tnsVertex2d(ui->R, ui->U);    tnsVertex2d(ui->R, ui->B);    tnsVertex2d(ui->L, ui->B);    tnsPackAs(GL_LINE_LOOP);}int la_DrawActiveUiItemOverlay(laUiItem *ui){    tnsUseNoTexture();    tnsColor4d(1, 1, 1, 1);    tnsVertex2d(ui->L - 1, ui->U - 1);    tnsVertex2d(ui->R + 1, ui->U - 1);    tnsVertex2d(ui->R + 1, ui->B + 1);    tnsVertex2d(ui->L - 1, ui->B + 1);    tnsPackAs(GL_LINE_LOOP);}int la_UiInBound(laUiItem *ui, int L, int R, int U, int B){    if (ui->R <= L || ui->L >= R || ui->U >= B || ui->B <= U) return 0;    return 1;}int la_UiInBoundEx(laUiItem *ui, laUiListDraw *uild){    laUiListDrawItem *uildi = uild->Items.pFirst;    laUiList *Target = uildi->Target;    int L, R, U, B;    if (!Target) return la_UiInBound(ui, uildi->L, uildi->R, uildi->U, uildi->B);    L = Target->L + Target->PanX + uildi->DifX;    R = Target->L + Target->PanX + uildi->DifX + (uildi->R - uildi->L);    B = Target->U + Target->PanY + uildi->DifY + (uildi->B - uildi->U);    U = Target->U + Target->PanY + uildi->DifY;    return la_UiInBound(ui, L, R, U, B);}int la_UiListInBoundEx(laUiList *uil, laUiListDraw *uild){    laUiListDrawItem *uildi = uild->Items.pFirst;    laUiList *Target = uildi->Target;    int L, R, U, B;    if (Target){        L = Target->L + Target->PanX + uildi->DifX;        R = Target->L + Target->PanX + uildi->DifX + (uildi->R - uildi->L);        B = Target->U + Target->PanY + uildi->DifY + (uildi->B - uildi->U);        U = Target->U + Target->PanY + uildi->DifY;        if (uil->R <= L || uil->L >= R || uil->U >= B || uil->B <= U) return 0;        return 1;    }else{        if (uil->R <= uildi->L || uil->L >= uildi->R || uil->U >= uildi->B || uil->B <= uildi->U) return 0;        return 1;    }}laUiItem *la_FindUiWithMark(laUiList *uil, char *mark){    laUiItem *ui = uil->UiItems.pFirst;    while (!strGetArgument(ui->Instructions, mark))        ui = ui->Item.pNext;    return ui;}laUiList *la_FindSubListWithInstance(laUiItem *ui, void *Instance){    laUiList *uil;    for (uil = ui->Subs.pFirst; uil; uil = uil->Item.pNext){        if (uil->Instance == Instance) return uil;    }    return uil;}void la_DrawUiListArrows(laUiList *uil, int L, int R, int U, int B, real* color){    int mx=(L+R)/2; int my=(U+B)/2;    if(uil->R-uil->PanX>R){ tnsDrawStringAuto("▷", color, R-LA_RH, R, my-LA_RH2, LA_TEXT_ALIGN_RIGHT); }    if(uil->L-uil->PanX<L){ tnsDrawStringAuto("◁", color, L, L+LA_RH, my-LA_RH2, LA_TEXT_ALIGN_LEFT); }    if(uil->U-uil->PanY<U){ tnsDrawStringAuto("△", color, mx-LA_RH2, mx+LA_RH2, U, LA_TEXT_ALIGN_CENTER); }    if(uil->B-uil->PanY>B){ tnsDrawStringAuto("▽", color, mx-LA_RH2, mx+LA_RH2, B-LA_RH, LA_TEXT_ALIGN_CENTER); }    tnsFlush();}void la_DrawUiListScrollerV(laUiList *uil, int DisplayOffset, int TotalH, int DisplayH, int UiR){    if(!uil->ScrollerShownV) return;        int W = LA_SCROLL_W, RM=_LA_THEME_PANEL->RM;    int Len = (int)((real)DisplayH / (real)TotalH * (real)DisplayH);    int Offset = (int)((real)DisplayOffset / (real)TotalH * (real)DisplayH);    int U = uil->U + Offset;    int B = U + Len;    int L = UiR - RM*2 - W;    int R = L + W;    if (B > U + DisplayH) B = U + DisplayH;    if (U < uil->U) U = uil->U;    if (B <= uil->U || U >= uil->B) return;    if (B > uil->U + DisplayH) B = uil->U + DisplayH;    if (U < uil->U) U = uil->U;    tnsUseNoTexture();    laBoxedTheme* bt=_LA_THEME_PANEL;    real* color=laThemeColor(bt, LA_BT_TEXT);    tnsColor4d(LA_COLOR3(color), 0.2);    tnsVertex2d(R-RM, uil->U);    tnsVertex2d(L+RM, uil->U);    tnsVertex2d(L+RM, uil->U + DisplayH);    tnsVertex2d(R-RM, uil->U + DisplayH);    tnsPackAs(GL_TRIANGLE_FAN);    tnsColor4d(LA_COLOR3(color), 0.5);    tnsVertex2d(R-RM, uil->U);    tnsVertex2d(L+RM, uil->U);    tnsVertex2d(L+RM, uil->U + DisplayH);    tnsVertex2d(R-RM, uil->U + DisplayH);    tnsPackAs(GL_LINE_LOOP);    tnsColor4d(LA_COLOR3(color), 1);    tnsVertex2d(R, U);    tnsVertex2d(L, U);    tnsVertex2d(L, B);    tnsVertex2d(R, B);    tnsPackAs(GL_TRIANGLE_FAN);    int HU=(U+B)/2+LA_RH2;    tnsDrawStringAuto("☰",laThemeColor(bt, LA_BT_BORDER),L-100,R+100,HU,LA_TEXT_REVERT_Y|LA_TEXT_ALIGN_CENTER);    tnsFlush();}void la_DrawUiListScrollerH(laUiList *uil, int DisplayOffset, int TotalW, int DisplayW, int UiB){    if(!uil->ScrollerShownH) return;        int W = LA_SCROLL_W,RM=_LA_THEME_PANEL->RM;    int Len = (int)((real)DisplayW / (real)TotalW * (real)DisplayW);    int Offset = (int)((real)DisplayOffset / (real)TotalW * (real)DisplayW);    int L = uil->L + Offset;    int R = L + Len;    int U = UiB - RM - W;    int B = U + W;    if (B > U + DisplayW) B = U + DisplayW;    if (U < uil->U) U = uil->U;    if (R <= uil->L || L >= uil->R) return;    if (R > uil->L + DisplayW) R = uil->L + DisplayW;    if (L < uil->L) L = uil->L;    tnsUseNoTexture();    laBoxedTheme* bt=_LA_THEME_PANEL;    real* color=laThemeColor(bt, LA_BT_TEXT);    tnsColor4d(LA_COLOR3(color), 0.2);    tnsVertex2d(uil->L,U+RM);    tnsVertex2d(uil->L,B-RM);    tnsVertex2d(uil->L + DisplayW,B-RM);    tnsVertex2d(uil->L + DisplayW,U+RM);    tnsPackAs(GL_TRIANGLE_FAN);    tnsColor4d(LA_COLOR3(color), 0.5);    tnsVertex2d(uil->L,U+RM);    tnsVertex2d(uil->L,B-RM);    tnsVertex2d(uil->L + DisplayW,B-RM);    tnsVertex2d(uil->L + DisplayW,U+RM);    tnsPackAs(GL_LINE_LOOP);    tnsColor4d(LA_COLOR3(color), 1);    tnsVertex2d(R, U);    tnsVertex2d(L, U);    tnsVertex2d(L, B);    tnsVertex2d(R, B);    tnsPackAs(GL_TRIANGLE_FAN);    int HU=(U+B)/2+LA_RH2;    tnsDrawStringAuto("↔",laThemeColor(bt, LA_BT_BORDER),L-100,R+100,HU,LA_TEXT_REVERT_Y|LA_TEXT_ALIGN_CENTER);    tnsFlush();}void la_DrawInstanceBkg(laUiList *uil, real* color, int LP, int RP){    tnsUseNoTexture();    tnsColor4dv(color);    tnsVertex2d(uil->L-LP, uil->U); tnsVertex2d(uil->R+RP, uil->U);    tnsVertex2d(uil->R+RP, uil->B); tnsVertex2d(uil->L-LP, uil->B);    tnsPackAs(GL_TRIANGLE_FAN);}void la_InitSocketRecord(laUiListDraw* uild, laUiList* container){    laSocketRecord* sr;    while(sr=lstPopItem(&uild->SocketRecord)){ memFree(sr); }    uild->WiresContainer=container;}void la_GetUiListOffsetUntil(laUiListDraw* uild, int* X, int* Y){    *X=*Y=0; for(laUiListDrawItem* lip=uild->Items.pLast;lip&&lip->Target;lip=lip->Item.pPrev){        if(lip->Target==uild->WiresContainer) break;        laUiList* uil=lip->Target; *X+=uil->PanX; *Y+=uil->PanY;    }}void la_RecordSocket(laUiListDraw* uild, laUiList* uil, laUiItem* ui){    laProp* p=ui->PP.LastPs->p; laPropContainer* pc=la_EnsureSubTarget(p,0);    int PanX, PanY;    if(pc==LA_PC_SOCKET_OUT){        laNodeOutSocket* s=ui->PP.EndInstance;        la_GetUiListOffsetUntil(uild, &s->RuntimePX, &s->RuntimePY);     }else{        laNodeInSocket* s=ui->PP.EndInstance; if(!s->Source) return;        laSocketRecord* sr=memAcquireSimple(sizeof(laSocketRecord));        sr->In=s; sr->Out=s->Source; lstAppendItem(&uild->SocketRecord, sr);    }}void la_RegenerateWireColors(){    if(MAIN.WireColorCache) free(MAIN.WireColorCache);    laTheme* t=MAIN.CurrentTheme;    MAIN.WireColorCache = calloc(1, sizeof(real)*4*MAIN.WireColorSlices);    real hsl[]={0.0,0.8,0.6}; hsl[1]=t->WireSaturation; hsl[2]=t->WireBrightness;    for(int i=0;i<MAIN.WireColorSlices;i++){        hsl[0]=(real)i/(real)MAIN.WireColorSlices;        tnsHSL2RGB(hsl, &MAIN.WireColorCache[i*4]); MAIN.WireColorCache[i*4+3]=t->WireTransparency;    }}void la_SendWireVerts(real x1, real y1, real x2, real y2, real circle_r){    tnsVector2d v1,vi,v2,v1s,v2s; real dist=0;    v1[0]=x1; v1[1]=y1; v2[0]=x2; v2[1]=y2;    tnsInterpolate2dv(v1,v2,0.5,vi);    if(MAIN.WireSaggyness>0.01){ dist=tnsDist2dv(v1,v2); vi[1]+=dist*MAIN.WireSaggyness; }    tnsVectorMinus2d(v1s,vi,v1); if(tnsLength2d(v1s)<1e-3){ v1s[0]=-1; v1s[1]=0; }else{ tnsNormalizeSelf2d(v1s); } tnsVectorMultiSelf2d(v1s,circle_r);    tnsVectorMinus2d(v2s,vi,v2); if(tnsLength2d(v2s)<1e-3){ v2s[0]=1; v2s[1]=0; }else{ tnsNormalizeSelf2d(v2s); } tnsVectorMultiSelf2d(v2s,circle_r);    tnsVectorAccum2d(v1, v1s); tnsVectorAccum2d(v2, v2s);    if(MAIN.WireSaggyness<0.01){ tnsVertex2d(v1[0],v1[1]); tnsVertex2d(v2[0],v2[1]); return; }    int seglen=3, steps=dist/seglen+1; real step=1.0f/steps;    tnsVertex2d(v1[0],v1[1]);    for(int i=1;i<=steps;i++){        real ratio=i==steps?1.0f:step*i;        tnsInterpolateTripple2d(v1,vi,v2,ratio, v1s);        tnsVertex2d(v1s[0],v1s[1]);    }}void la_DrawNodeWires(laUiListDraw* uild){    if(!uild->SocketRecord.pFirst && !MAIN.tNodeIn->Source){ return; }    laBoxedTheme* bt=_LA_THEME_SOCKET;    tnsUseNoTexture();#define _RSLICES 16    real v[_RSLICES*4]; int idx[_RSLICES*2+2]; real r=LA_RH2/TNS_MAX2(uild->WiresContainer->Scale,1);    for(laSocketRecord*sr=uild->SocketRecord.pFirst;sr;sr=sr->Item.pNext){        int cid=sr->In->ColorId%MAIN.WireColorSlices*4;        int inx=sr->In->RuntimeX+sr->In->RuntimePX, iny=sr->In->RuntimeY+sr->In->RuntimePY;        int outx=sr->Out->RuntimeX+sr->Out->RuntimePX, outy=sr->Out->RuntimeY+sr->Out->RuntimePY;        if(sr->Out==MAIN.tNodeOut){ outx=inx+MAIN.tNodeOut->RuntimeX+MAIN.tNodeOut->RuntimePX; outy=iny+MAIN.tNodeOut->RuntimeY+MAIN.tNodeOut->RuntimePY; }        tnsMakeRing2d(v,idx,_RSLICES, inx, iny, r, r*0.6);        tnsVertexArray2d(v,_RSLICES*2); tnsIndexArray(idx, _RSLICES*2+2);        tnsColor4d(LA_COLOR3(&MAIN.WireColorCache[cid]),1); tnsPackAs(GL_TRIANGLE_STRIP);        tnsMakeRing2d(v,idx,_RSLICES, outx, outy, r, r*0.6);        tnsVertexArray2d(v,_RSLICES*2); tnsIndexArray(idx, _RSLICES*2+2);        tnsColor4d(LA_COLOR3(&MAIN.WireColorCache[cid]),1); tnsPackAs(GL_TRIANGLE_STRIP);    }    if(MAIN.tNodeIn->Source){        laNodeInSocket* ins=MAIN.tNodeIn; laNodeOutSocket* outs=ins->Source;        int cid=ins->ColorId%MAIN.WireColorSlices*4;        int outx=outs->RuntimeX+outs->RuntimePX, outy=outs->RuntimeY+outs->RuntimePY;        int inx=ins->RuntimeX+ins->RuntimePX+outx, iny=ins->RuntimeY+ins->RuntimePY+outy;        tnsMakeRing2d(v,idx,_RSLICES, inx, iny, r, r*0.6);        tnsVertexArray2d(v,_RSLICES*2); tnsIndexArray(idx, _RSLICES*2+2);        tnsColor4d(LA_COLOR3(&MAIN.WireColorCache[cid]),1); tnsPackAs(GL_TRIANGLE_STRIP);        tnsMakeRing2d(v,idx,_RSLICES, outx, outy, r, r*0.6);        tnsVertexArray2d(v,_RSLICES*2); tnsIndexArray(idx, _RSLICES*2+2);        tnsColor4d(LA_COLOR3(&MAIN.WireColorCache[cid]),1); tnsPackAs(GL_TRIANGLE_STRIP);    }#undef _RSLICES    tnsFlush();    int ww=MAIN.WireThickness*TNS_MIN2(uild->WiresContainer->Scale,1);    glLineWidth(ww);    for(laSocketRecord*sr=uild->SocketRecord.pFirst;sr;sr=sr->Item.pNext){        int cid=sr->In->ColorId%MAIN.WireColorSlices*4;        int inx=sr->In->RuntimeX+sr->In->RuntimePX, iny=sr->In->RuntimeY+sr->In->RuntimePY;        int outx=sr->Out->RuntimeX+sr->Out->RuntimePX, outy=sr->Out->RuntimeY+sr->Out->RuntimePY;        if(sr->Out==MAIN.tNodeOut){ outx=inx+MAIN.tNodeOut->RuntimeX+MAIN.tNodeOut->RuntimePX; outy=iny+MAIN.tNodeOut->RuntimeY+MAIN.tNodeOut->RuntimePY; }        la_SendWireVerts(inx, iny, outx, outy, r*0.9);        tnsColor4dv(&MAIN.WireColorCache[cid]); tnsPackAs(GL_LINE_STRIP);    }    if(MAIN.tNodeIn->Source){        laNodeInSocket* ins=MAIN.tNodeIn; laNodeOutSocket* outs=ins->Source;        int cid=ins->ColorId%MAIN.WireColorSlices*4;        int outx=outs->RuntimeX+outs->RuntimePX, outy=outs->RuntimeY+outs->RuntimePY;        int inx=ins->RuntimeX+ins->RuntimePX+outx, iny=ins->RuntimeY+ins->RuntimePY+outy;                la_SendWireVerts(inx, iny, outx, outy, r*0.9);        tnsColor4dv(&MAIN.WireColorCache[cid]); tnsPackAs(GL_LINE_STRIP);    }    tnsFlush();    glLineWidth(1);    la_InitSocketRecord(uild,0);}void la_SwitchThemeQuick(laTheme* t, laTheme* DefaultTheme){    if(!DefaultTheme){return;} MAIN.CurrentTheme = t?t:DefaultTheme; t=MAIN.CurrentTheme;    for(laBoxedTheme* bt = t->BoxedThemes.pFirst;bt;bt=bt->Item.pNext){ (*bt->BackRef) = bt; }}int la_DrawUiListRecursive(laUiListDraw *uild, laUiList *uil, int L, int R, int U, int B, int LimH, int ConditionStackLevel, int GlobalX, int GlobalY, int RegisterNodes){    laUiItem *ui;    laBoxedTheme *bt;    laUiList *sub;    laUiListDrawItem *uildi;    int Ret = 0;    if (!uil) return 0;    //printf("d %d\n",MAIN.CurrentPanel->FrameDistinguish);    ui = uil->UiItems.pFirst;    if(uil->PanY<0){uil->PanY=0;}    if (!la_SetUpUiListMatrix(uild, uil, L, R, LimH, B - U, GlobalX, GlobalY)) return 0;    uil->SaveScale=MAIN.UiScale;    MAIN.UiScale*=uil->Scale;    MAIN.ScaledUiRowHeight=MAIN.UiRowHeight*MAIN.UiScale;    for (; ui;){ if(ui->Type==&_LA_UI_INVISIBLE){ ui=ui->Item.pNext; continue; }        bt = ui->Type->Theme ? (*ui->Type->Theme) : 0;        if (ui->Type == &_LA_UI_CONDITION){            laConditionUiExtraData *cued = ui->Extra;            la_StepExpression(cued->Expression);            cued->IsTrue = la_DoSingleExpression(cued->Expression);            if (!cued->IsTrue){                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                ui = ui->Item.pNext;            }            continue;        }else if (ui->Type == &_LA_UI_CONDITION_END){            ui = ui->Item.pNext;            continue;        }else if (ui->Type == &_LA_UI_CONDITION_ELSE){            laConditionUiExtraData *cued = ((laConditionUiExtraData *)ui->Extra)->EndUi->Extra;            if (cued->IsTrue) ui = cued->EndUi;            else                ui = ui->Item.pNext;            continue;        }else if (ui->Type == _LA_UI_CONDITION_TOGGLE){            laConditionUiExtraData *cued = ui->Extra;            ui->Type->Draw(ui, LA_RH);            if (ui->State == LA_UI_NORMAL){                cued->IsTrue = 0;                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                cued->IsTrue = 1;                ui = ui->Item.pNext;            }            continue;        }        if (ui->AnimationDistinguish != MAIN.CurrentPanel->FrameDistinguish) Ret = 1;        int NeedDraw=0;        if (la_UiInBoundEx(ui, uild)){ NeedDraw=1; }        if(NeedDraw){            if (!ui->Type->Draw){ la_DrawUiItem(ui); tnsFlush();            }else{ ui->Type->Draw(ui, LA_RH); }            if (ui->Type->Tag & LA_UI_TAG_IS_OFFSCREEN){                tnsFlush();                tnsDrawToOffscreen(MAIN.CurrentPanel->OffScr, 1, 0);                tnsResetViewMatrix();            }            if (ui->Type->Tag & (LA_UI_TAG_NEED_REBUILD)){                la_RebuildCurrentUiListMatrix(uild, uil, LimH, B - U);                if (ui->CanvasTemplate->SecondDraw) ui->CanvasTemplate->SecondDraw(ui, LA_RH);                tnsFlush();            }        }        if(NeedDraw || RegisterNodes){            if (RegisterNodes && ui->Type==_LA_UI_NODE_SOCKET){ la_RecordSocket(uild,uil,ui); }            if (ui->Type == _LA_UI_FIXED_GROUP ||                ui->Type == _LA_UI_TAB ||                ui->Type == _LA_UI_COLLECTION_SINGLE ||                ui->Type == _LA_UI_COLLECTION_SELECTOR && (ui->Subs.pFirst || ui->Page)){                if (!ui->Page){ ui = ui->Item.pNext; continue; }                tnsFlush(); int DoNodes=RegisterNodes; int NoDecal=ui->Flags&LA_UI_FLAGS_NO_DECAL;                if(ui->Flags&LA_UI_FLAGS_NODE_CONTAINER){ la_InitSocketRecord(uild, ui->Page); DoNodes=1; }                Ret += la_DrawUiListRecursive(uild, ui->Page, ui->L+(NoDecal?0:bt->LM), ui->R-(NoDecal?0:bt->RM), U, B,                    (ui->Page->HeightCoeff ? ui->B - ui->Page->U : 10000) -(NoDecal?0:bt->LM), ConditionStackLevel, GlobalX, GlobalY, DoNodes);                if (ui->Page->ScrollerShownH){ la_DrawUiListScrollerH(ui->Page, ui->Page->PanX,                    ui->Page->R-ui->Page->L-bt->RM-bt->LM, ui->R-ui->Page->L-bt->RM-bt->LM-(ui->Page->ScrollerShownV?LA_SCROLL_W:0),ui->B); }                if (ui->Page->HeightCoeff) la_DrawUiListScrollerV(ui->Page, ui->Page->PanY,                    ui->Page->B-ui->Page->U-(NoDecal?0:bt->TM-bt->BM), ui->B-ui->Page->U-(NoDecal?0:bt->TM-bt->BM)-(ui->Page->ScrollerShownH?LA_SCROLL_W+bt->RM:0),ui->R);                if (ui->Page->AllowScale){ la_DrawUiListArrows(ui->Page,ui->L, ui->R, ui->Page->U, ui->B-LA_SCROLL_W-bt->BM*2, laThemeColor(bt, LA_BT_BORDER)); }            }elif (ui->Type == _LA_UI_COLLECTION){                int CanGetState = laCanGetState(ui->PP.LastPs->p);                int CanGetTheme = laCanGetTheme(ui->PP.LastPs->p);laTheme* OriginalTheme=MAIN.CurrentTheme;                void *Active = laGetActiveInstanceStrict(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance);                void* SaveInstance = ui->PP.EndInstance;                for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){                    int State;                    ui->PP.EndInstance = sub->Instance;                    if ((!la_UiListInBoundEx(sub, uild)) && (!RegisterNodes)) continue;                    if(!(ui->Flags&LA_UI_COLLECTION_NO_HIGHLIGHT) && NeedDraw){                        if (CanGetState){                            State = laGetUiState(ui->PP.LastPs->p, sub->Instance);                            la_DrawInstanceBkg(sub, laAccentColor(LA_BT_NORMAL),bt->LP,bt->RP);                        }elif (sub->Instance == Active){                            la_DrawInstanceBkg(sub, laAccentColor(LA_BT_NORMAL),bt->LP,bt->RP);                        }                    }                    if(sub->TabName && sub->TabName->Ptr){                        int NoDecal=ui->Flags&LA_UI_FLAGS_NO_DECAL;                        int NoGap=ui->Flags&LA_UI_FLAGS_NO_GAP;                        tnsDrawStringAuto(transLate(sub->TabName->Ptr),laThemeColor(bt,LA_BT_DISABLED|LA_BT_TEXT),                            ui->L+(NoDecal?0:bt->LM)+(NoGap?0:bt->LP),ui->R,sub->U-LA_RH,LA_TEXT_MONO);                        tnsFlush();                    }                    if(CanGetTheme){                        laTheme* t=laGetUiTheme(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, ui->PP.EndInstance);                        la_SwitchThemeQuick(t, OriginalTheme);                        if(t) la_DrawInstanceBkg(sub, laThemeColor(_LA_THEME_FLOATING_PANEL ,LA_BT_NORMAL),bt->LP,bt->RP);                    }                    tnsFlush();                    Ret += la_DrawUiListRecursive(uild, sub, L, R, U, B, 10000, ConditionStackLevel, GlobalX, GlobalY, RegisterNodes);                                        if(CanGetTheme){ la_SwitchThemeQuick(0, OriginalTheme); }                }                //ui->PP.EndInstance = Active;                ui->PP.EndInstance = SaveInstance;            }elif (ui->Type == _LA_UI_CANVAS){                if(!(ui->Flags&LA_UI_FLAGS_NO_OVERLAY)){                    for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){                        tnsFlush();                        Ret += la_DrawUiListRecursive(uild, sub, L-1, R+1, U-1, B+1, ui->B-bt->TP-bt->BP-bt->BM-bt->TM, ConditionStackLevel, GlobalX, GlobalY, RegisterNodes);                    }                }            }            ui = ui->Item.pNext;        }else{            ui = ui->Item.pNext;        }    }    tnsFlush();    if(uild->WiresContainer == uil){ la_DrawNodeWires(uild); }    la_RestoreLastUiListMatrix(uild, B - U);    MAIN.UiScale=uil->SaveScale;    MAIN.ScaledUiRowHeight=MAIN.UiRowHeight*MAIN.UiScale;    return Ret;}int la_DrawPanelScrollBarV(int L, int R, int U, int B, real Total, real Range, real Offset){    int Begin = U + (int)(Offset / Total * (real)(B - U)) + 3;    int End = Begin + (int)(Range / Total * (real)(B - U)) - 3;    tnsUseNoTexture();    tnsColor4d(1, 1, 1, 1);    tnsVertex2d(L, U);    tnsVertex2d(R, U);    tnsVertex2d(R, B);    tnsVertex2d(L, B);    tnsPackAs(GL_LINE_LOOP);    tnsVertex2d(L + 3, Begin);    tnsVertex2d(R - 3, Begin);    tnsVertex2d(R - 3, End);    tnsVertex2d(L + 3, End);    tnsPackAs(GL_LINE_LOOP);}int laIsInUiItem(laUiItem *ui, int x, int y){    if (x < ui->L || x > ui->R || y < ui->U || y > ui->B) return 0;    return 1;}int laIsInBound(int x, int y, int l, int r, int u, int b){    if (x < l || x > r || y < u || y > b) return 0;    return 1;}laColumn *la_DetectSplit(laColumn *Root, int LocalX);laUiItem *la_DetectUiItemRecursive(laUiList *uil, int x, int y, int LimB, laListHandle *LocalBuf, int Deep){    laUiItem *ui, *tui;    laBoxedTheme *bt;    laUiList *sub;    int CPB = 0;    if (!uil || (LimB && y > LimB)) return 0;    x += uil->PanX;    y += uil->PanY;    for (ui = uil->UiItems.pFirst; ui;){        bt = ui->Type->Theme ? (*ui->Type->Theme) : 0;        if (ui->Type == &_LA_UI_CONDITION){            laConditionUiExtraData *cued = ui->Extra;            //la_StepExpression(cued->Expression); for some reason we can't step here, only step in update :thinking:            cued->IsTrue = la_DoSingleExpression(cued->Expression);            if (!cued->IsTrue){                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                ui = ui->Item.pNext;            }            continue;        }else if (ui->Type == &_LA_UI_CONDITION_END){            ui = ui->Item.pNext;            continue;        }else if (ui->Type == &_LA_UI_CONDITION_ELSE){            laConditionUiExtraData *cued = ((laConditionUiExtraData *)ui->Extra)->EndUi->Extra;            if (cued->IsTrue) ui = cued->EndUi;            else                ui = ui->Item.pNext;            continue;        }else if (ui->Type == _LA_UI_CONDITION_TOGGLE){            laConditionUiExtraData *cued = ui->Extra;            if (laIsInUiItem(ui, x, y)){                lstAppendPointer(LocalBuf, uil);                return ui;            }            if (ui->State == LA_UI_NORMAL){                cued->IsTrue = 0;                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                cued->IsTrue = 1;                ui = ui->Item.pNext;            }            continue;        }        //printf("%s > ",ui->Type->Identifier?ui->Type->Identifier:"-");        if (ui->Type != _LA_UI_COLLECTION && ui->Type != _LA_UI_COLLECTION_SINGLE &&            ui->Type != _LA_UI_FIXED_GROUP && ui->Type != _LA_UI_TAB && ui->Type != _LA_UI_CANVAS && laIsInUiItem(ui, x, y)){            int Add=1; if(ui->Type==_LA_UI_COLUMN_ADJUSTER){                if(!la_DetectSplit(ui->C, x)) Add=0;            }            if(Add){ lstAppendPointer(LocalBuf, uil); return ui; }        }        if ((ui->Type == _LA_UI_FIXED_GROUP || ui->Type == _LA_UI_TAB) && (ui->Subs.pFirst || ui->Page)){            if (ui->Page->HeightCoeff) CPB = ui->B;            else CPB = ui->Page->B;            if (laIsInBound(x, y, ui->Page->L, ui->Page->R, ui->Page->U, CPB)){                if (tui = la_DetectUiItemRecursive(ui->Page, x /* + ui->Page->PanX*/, y /*+ ui->Page->PanY*/, CPB, LocalBuf, Deep)){                    lstAppendPointer(LocalBuf, uil);                    return tui;                }            }else if (laIsInUiItem(ui, x, y)){                lstAppendPointer(LocalBuf, uil);return ui;            }        }        if (ui->Type == _LA_UI_COLLECTION || ui->Type==_LA_UI_COLLECTION_SINGLE){            if (laIsInUiItem(ui, x, y)){                lstAppendPointer(LocalBuf, uil);                if (ui->Subs.pFirst) ((laUiList *)ui->Subs.pFirst)->HeightCoeff = LimB;                if(Deep){                    for(laUiList* iuil=ui->Subs.pFirst;iuil;iuil=iuil->Item.pNext){                        if (laIsInBound(x, y, iuil->L, iuil->R, iuil->U, iuil->B)){                            if (tui = la_DetectUiItemRecursive(iuil, x , y , iuil->B, LocalBuf, Deep)){                                lstAppendPointer(LocalBuf, iuil);                                return tui;                            }                        }                    }                }                return ui;            }        }        if (ui->Type == _LA_UI_CANVAS){            if(!(ui->Flags&LA_UI_FLAGS_NO_OVERLAY)){                for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){                    if (tui = la_DetectUiItemRecursive(sub, x, y, ui->B, LocalBuf, Deep)){                        lstAppendPointer(LocalBuf, uil);                        return tui;                    }                }            }            if (laIsInUiItem(ui, x, y)){                lstAppendPointer(LocalBuf, uil);                return ui;            }        }        ui = ui->Item.pNext;    }    return 0;}laUiItem *la_DetectSocketRecursive(laUiList* uil, int x, int y, int LimB, laPropContainer* PCInOrOut){    laListHandle Locals={0};    laUiItem* ui=la_DetectUiItemRecursive(uil, x,y,LimB,&Locals, 1);    while(lstPopPointer(&Locals));    //printf("%s\n", ui?ui->Type->Identifier:"?");    if(ui && ui->Type==_LA_UI_NODE_SOCKET){        laProp* p=ui->PP.LastPs->p; laPropContainer* pc=la_EnsureSubTarget(p,0);        if(pc==PCInOrOut) return ui;    }    return 0;}laUiList *la_DetectUiListRecursive(laUiList *uil, int x, int y, int LimH,                                   laUiItem **ParentUi, laUiList **ScrollUil, laUiList **ContainerParent, int InToContainerUI, laUiItem *Exception){    laUiItem *ui = uil->UiItems.pFirst;    laBoxedTheme *bt;    laUiList *tuil;    laUiList *sub;    int CPB = 0;    x += uil->PanX;    y += uil->PanY;    if (y > LimH) return uil;    if (/*uil->ScrollerShownV && */ laIsInBound(x, y, uil->R, uil->R+LA_SCROLL_W+4, uil->U, uil->B) ||        /*uil->ScrollerShownH && */ laIsInBound(x, y, uil->L, uil->R, uil->B, uil->B+LA_SCROLL_W+4)){        if (ScrollUil) *ScrollUil = uil; /* if (ParentUi)*ParentUi = uil;*/        return uil;    }    for (ui = uil->UiItems.pFirst; ui;){        bt = ui->Type->Theme ? (*ui->Type->Theme) : 0;        if (ui->Type == &_LA_UI_CONDITION){            laConditionUiExtraData *cued = ui->Extra;            //la_StepExpression(cued->Expression);            cued->IsTrue = la_DoSingleExpression(cued->Expression);            if (!cued->IsTrue){                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                ui = ui->Item.pNext;            }            continue;        }        if (ui->Type == &_LA_UI_CONDITION_END){            ui = ui->Item.pNext;            continue;        }else if (ui->Type == &_LA_UI_CONDITION_ELSE){            laConditionUiExtraData *cued = ((laConditionUiExtraData *)ui->Extra)->EndUi->Extra;            if (cued->IsTrue) ui = cued->EndUi;            else                ui = ui->Item.pNext;            continue;        }else if (ui->Type == _LA_UI_CONDITION_TOGGLE){            laConditionUiExtraData *cued = ui->Extra;            if (ui->State == LA_UI_NORMAL){                cued->IsTrue = 0;                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                cued->IsTrue = 1;                ui = ui->Item.pNext;            }            continue;        }        if (InToContainerUI && ui != Exception){            if (ui->Type == _LA_UI_CANVAS && !(ui->Flags&LA_UI_FLAGS_NO_OVERLAY)){                if (ContainerParent) (*ContainerParent) = uil;                if (ParentUi) *ParentUi = ui;                for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){                    //if (y > LimH) return uil;                    if (laIsInBound(x, y, sub->L, sub->R, sub->U, sub->B) && (tuil = la_DetectUiListRecursive(sub, x, y, ui->B, ParentUi, ScrollUil, ContainerParent, InToContainerUI, Exception))){                        return tuil;                    }                }            }        }        if ((ui->Type == _LA_UI_FIXED_GROUP || ui->Type == _LA_UI_TAB) && (ui->Subs.pFirst || ui->Page)){            if (ui->Page->HeightCoeff) CPB = ui->B;            else CPB = ui->Page->B;            if (ui->Page->ScrollerShownV && laIsInBound(x, y, ui->R - LA_SCROLL_W - bt->RP*2, ui->R, ui->Page->U, CPB)){                if (ScrollUil) *ScrollUil = ui->Page; if (ParentUi) *ParentUi = ui;            }elif (ui->Page->ScrollerShownH && laIsInBound(x, y, ui->Page->L, ui->Page->R, ui->B - LA_SCROLL_W - bt->BP*2, ui->B)){                if (ScrollUil) *ScrollUil = ui->Page; if (ParentUi) *ParentUi = ui;            }elif (laIsInBound(x, y, ui->Page->L, ui->Page->R, ui->Page->U, CPB)){                if (ParentUi) *ParentUi = ui;                 if (tuil = la_DetectUiListRecursive(ui->Page, x, y, CPB, ParentUi, ScrollUil, ContainerParent, InToContainerUI, Exception)) return tuil;            }        }        ui = ui->Item.pNext;    }    return uil;}laUiList *la_DetectUiListRecursiveDeep(laUiList *uil, int x, int y, int LimH, laUiItem **ParentUi, laUiList **ScrollUil,                                       laUiList **ContainerParent, int InToContainerUI, laUiItem *Exception, laListHandle* levels){    laUiItem *ui = uil->UiItems.pFirst;    laBoxedTheme *bt;    laUiList *tuil;    laUiList *sub;    int CPB = 0;    laUiListRecord* uilr=lstAppendPointerSized(levels, uil, sizeof(laUiListRecord));    x += uil->PanX;    y += uil->PanY;    if (y > LimH) return uil;        if (/*uil->ScrollerShownV && */ laIsInBound(x, y, uil->R, uil->R+LA_SCROLL_W+4, uil->U, uil->B) ||        /*uil->ScrollerShownH && */ laIsInBound(x, y, uil->L, uil->R, uil->B, uil->B+LA_SCROLL_W+4)){        if (ScrollUil) *ScrollUil = uil; /* if (ParentUi)*ParentUi = uil;*/        return uil;    }    for (ui = uil->UiItems.pFirst; ui;){        bt = ui->Type->Theme ? (*ui->Type->Theme) : 0;        if (ui->Type == &_LA_UI_CONDITION){            laConditionUiExtraData *cued = ui->Extra;            //la_StepExpression(cued->Expression);            cued->IsTrue = la_DoSingleExpression(cued->Expression);            if (!cued->IsTrue){                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                ui = ui->Item.pNext;            }            continue;        }        if (ui->Type == &_LA_UI_CONDITION_END){            ui = ui->Item.pNext;            continue;        }else if (ui->Type == &_LA_UI_CONDITION_ELSE){            laConditionUiExtraData *cued = ((laConditionUiExtraData *)ui->Extra)->EndUi->Extra;            if (cued->IsTrue) ui = cued->EndUi;            else                ui = ui->Item.pNext;            continue;        }else if (ui->Type == _LA_UI_CONDITION_TOGGLE){            laConditionUiExtraData *cued = ui->Extra;            if (ui->State == LA_UI_NORMAL){                cued->IsTrue = 0;                ui = cued->ElseUi ? cued->ElseUi : cued->EndUi;            }else{                cued->IsTrue = 1;                ui = ui->Item.pNext;            }            continue;        }        if (InToContainerUI && ui != Exception){            if (ui->Type == _LA_UI_CANVAS && !(ui->Flags&LA_UI_FLAGS_NO_OVERLAY)){                if (ContainerParent) (*ContainerParent) = uil;                if (ParentUi) *ParentUi = ui; uilr->pui=ui;                for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){                    //if (y > LimH) return uil;                    if (laIsInBound(x, y, sub->L, sub->R, sub->U, sub->B) && (tuil = la_DetectUiListRecursiveDeep(sub, x, y, ui->B, ParentUi, ScrollUil, ContainerParent, InToContainerUI, Exception, levels))){                        return tuil;                    }                }            }        }        if ((ui->Type == _LA_UI_FIXED_GROUP || ui->Type == _LA_UI_TAB) && (ui->Subs.pFirst || ui->Page)){            if (ui->Page->HeightCoeff) CPB = ui->B;            else CPB = ui->Page->B;            if (ui->Page->ScrollerShownV && laIsInBound(x, y, ui->R - LA_SCROLL_W - bt->RP*2, ui->R, ui->Page->U, CPB)){                if (ScrollUil) *ScrollUil = ui->Page; if (ParentUi) *ParentUi = ui; uilr->pui=ui;            }elif (ui->Page->ScrollerShownH && laIsInBound(x, y, ui->Page->L, ui->Page->R, ui->B - LA_SCROLL_W - bt->BP*2, ui->B)){                if (ScrollUil) *ScrollUil = ui->Page; if (ParentUi) *ParentUi = ui; uilr->pui=ui;            }elif (laIsInBound(x, y, ui->Page->L, ui->Page->R, ui->Page->U, CPB)){                if (ParentUi) *ParentUi = ui; uilr->pui=ui;                if (tuil = la_DetectUiListRecursiveDeep(ui->Page, x, y, CPB, ParentUi, ScrollUil, ContainerParent, InToContainerUI, Exception, levels)) return tuil;            }        }        if ((ui->PP.LastPs && ui->PP.LastPs->p->PropertyType == LA_PROP_SUB) && (ui->Subs.pFirst || ui->Page)){            if (ui->Page->HeightCoeff) CPB = ui->B;            else                CPB = ui->Page->B;            if (laIsInBound(x, y, ui->Page->R, ui->Page->R + LA_SCROLL_W + bt->RM, ui->Page->U, CPB)){                if (ScrollUil) *ScrollUil = ui->Page;                if (ParentUi) *ParentUi = ui; uilr->pui=ui;            }            if (laIsInBound(x, y, ui->Page->L, ui->Page->R, ui->Page->U, CPB)){                if (ParentUi) *ParentUi = ui; uilr->pui=ui;                if (tuil = la_DetectUiListRecursiveDeep(ui->Page, x, y, CPB, ParentUi, ScrollUil, ContainerParent, InToContainerUI, Exception, levels)) return tuil;            }        }        ui = ui->Item.pNext;    }    return uil;}int la_TestUiListMinumWidth(laUiList *uil){    laUiItem *ui, *tui;    laBoxedTheme *bt;    laUiList *sub;    int CPB = 0;    int W = 0;    int tW, sW, RowMode=0, rW;    void *Restore;    for (ui = uil->UiItems.pFirst; ui;){        bt = ui->Type->Theme ? (*ui->Type->Theme) : 0;        if ((ui->Type == _LA_UI_FIXED_GROUP || ui->Type == _LA_UI_TAB) && (ui->Subs.pFirst || ui->Page)){            tW = la_TestUiListMinumWidth(ui->Page) + bt->LP + bt->RP;            tW = (int)((float)tW / ui->C->PreWidth + 2);            if (W < tW) W = tW;        }elif (ui->Type == _LA_UI_COLLECTION){            Restore = ui->PP.EndInstance;            tW = 0; sW = 0;            for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){                ui->PP.EndInstance = sub->Instance;                sW = la_TestUiListMinumWidth(sub) + bt->LP + bt->RP;                if (sW > tW) tW = sW;            }            ui->PP.EndInstance = Restore;            tW = (int)((float)tW / ui->C->PreWidth + 2);            tW *= (ui->SymbolID > 0 ? ui->SymbolID : 1);            if (W < tW) W = tW;        }elif (ui->Type==&_LA_UI_ROW_BEGIN){            RowMode=1; rW=0;        }elif (ui->Type==&_LA_UI_ROW_END){            RowMode=0; rW=(int)((float)rW / ui->C->PreWidth + 2); if (W < rW) W = rW;        }elif (ui->Type->GetMinWidth){            tW = ui->Type->GetMinWidth(ui) + bt->LP + bt->RP;            if(RowMode){ rW+=tW; }else{ tW = (int)((float)tW / ui->C->PreWidth + 2); if (W < tW) W = tW; }        }        ui = ui->Item.pNext;    }    return W;}void la_InitLLVM(){    //LLVMLinkInMCJIT();    //LLVMInitializeNativeTarget();    //LLVMInitializeNativeAsmPrinter();    //LLVMInitializeNativeAsmParser();    //   MAIN.llvmContext = LLVMGetGlobalContext();    //MAIN.llvmModule = LLVMModuleCreateWithNameInContext(LA_NODE_MAIN_MODULE_NAME, MAIN.llvmContext);}//==================================================================================================void la_FreeKeyMapItem(laKeyMapItem* kmi){    if(kmi->Instructions) strSafeDestroy(&kmi->Instructions);    if(kmi->Operation) strSafeDestroy(&kmi->Operation);    if(kmi->Action.Go) la_FreePropStepCache(kmi->Action.Go);    if(kmi->Base.Go) la_FreePropStepCache(kmi->Action.Go);    memFree(kmi);}laKeyMapItem *laAssignNewKey(laKeyMapper *km, char *Path, char *Operation, char SelectBase, int SpecialKeyBits, int EventType, int Key, char *ExtraInstructions){    laKeyMapItem *kmi;    if (!km) return 0;    kmi = memAcquire(sizeof(laKeyMapItem));    if (la_GetPropFromPath(&kmi->Base, 0, Path, 0)){        la_GetPropFromPath(&kmi->Action, &kmi->Base, Operation, 0);    }else{        strSafeSet(&kmi->Operation, Operation);    }    strSafeSet(&kmi->Instructions, ExtraInstructions);    kmi->SpecialKeyBits = SpecialKeyBits;    kmi->EventType = EventType;    kmi->Key = tolowerGuarded(Key);    kmi->SelectBase = SelectBase;    lstAppendItem(&km->Items, kmi);    return kmi;}int laKeyMapExecuteEvent(laOperator *from, laKeyMapper *km, laEvent *e){    laKeyMapItem *kmi; int inv=0;    char *instructions;    if(e->type==LA_MOUSEMOVE) return 0;    for (kmi = km->Items.pFirst; kmi; kmi = kmi->Item.pNext){        if (kmi->SpecialKeyBits == e->SpecialKeyBit &&            kmi->EventType == e->type && ((kmi->Key == e->Input) || (kmi->Key == e->key))){            instructions = kmi->Instructions ? kmi->Instructions->Ptr : 0;            if (kmi->Operation)                laInvoke(from, kmi->Operation->Ptr, e, 0, instructions, 0);            else                laInvoke(from, ((laOperatorProp *)&kmi->Action.LastPs)->OperatorID, e, &kmi->Base, instructions, 0);            inv = 1;        }    }    return inv;}int laKeyMapExecuteEventEx(laOperator *from, laPropPack *UiExtra, laKeyMapper *km, laEvent *e){    laKeyMapItem *kmi;    char *instructions;    int inv = 0; int lx = -1, ly = -1;    if(e->type==LA_MOUSEMOVE) return 0;    for (kmi = km->Items.pFirst; kmi; kmi = kmi->Item.pNext){        if (kmi->SpecialKeyBits == e->SpecialKeyBit &&            kmi->EventType == e->type && ((kmi->Key == e->Input) || (kmi->Key == e->key))){            if (e->Localized){                lx = e->x;                ly = e->y;                laLocalToWindow(from, MAIN.ToPanel, &e->x, &e->y);                e->Localized = 0;            }            instructions = kmi->Instructions ? kmi->Instructions->Ptr : 0;            if (kmi->SelectBase == LA_KM_SEL_UI_EXTRA){                laInvoke(from, kmi->Operation->Ptr, e, UiExtra, instructions, 0);            }elif (kmi->SelectBase == LA_KM_SEL_PANEL){                laInvoke(from, kmi->Operation->Ptr, e, &((laPanel *)MAIN.ToPanel)->PP, instructions, 0);            }elif (kmi->Operation){                laInvoke(from, kmi->Operation->Ptr, e, 0, instructions, 0);            }else{                laInvoke(from, ((laOperatorProp *)&kmi->Action.LastPs)->OperatorID, e, &kmi->Base, instructions, 0);            }            inv = 1;            if (lx >= 0){                e->x = lx;                e->y = ly;                e->Localized = 1;            }        }    }    return inv;}void la_DefaultOperatorParser(laStringSplitor *ss, char *IconID, char *DisplayString);void la_DestroyOperatorType(laOperatorType* at){    //if(at->PC) la_FreePropertyContainer(at->PC);    memFree(at);}laOperatorType *laCreateOperatorType(const char *ID, const char *Name, const char *Description,                                     laCheckFunc Check, laInitFunc Init, laExitFunc Exit, laInvokeFunc Invoke, laModalFunc Modal,                                     uint32_t IconID, int ExtraMark){    laOperatorType *at = memAcquire(sizeof(laOperatorType));    at->Identifier = ID;    at->Name = Name;    at->Description = Description;    at->Check = Check;    at->Invoke = Invoke;    at->Init = Init;    at->Exit = Exit;    at->Modal = Modal;    at->IconID = IconID;    at->ExtraMark = ExtraMark;    at->ParseArgs = la_DefaultOperatorParser;    hsh256InsertItemCSTR(&MAIN.OperatorTypeHash, at, at->Identifier);    return at;}laPropContainer* laDefineOperatorProps(laOperatorType* ot, int HyperLevel){    ot->PC = memAcquire(sizeof(laPropContainer));    ot->PC->Identifier = ot->Identifier;    ot->PC->Hyper = HyperLevel;     return ot->PC;}laOperator *la_CreateOperator(laOperatorType *at){    laOperator *a = CreateNew(laOperator);    a->Type = at;    if (at->PC && at->PC->Props.pFirst){        a->PP.LastPs = memAcquireSimple(sizeof(laPropStep));        a->PP.LastPs->p = memAcquire(sizeof(laSubProp));        a->PP.LastPs->p->SubProp = at->PC;        a->PP.LastPs->p->PropertyType = LA_PROP_SUB;        a->PP.LastPs->p->Identifier = at->PC->Identifier;        a->PP.LastPs->Type = U'.';    }    return a;}int la_OperatorTypeByID(laOperatorType *a, char *id){    return (!strcmp(a->Identifier, id));}laOperatorType *laGetOperatorType(const char *ID){    return hsh256FindItemSTR(&MAIN.OperatorTypeHash, la_OperatorTypeByID, ID);}int laOperatorExistsT(laOperatorType* at){    if (!at) return 0;    for (laOperator *a = MAIN.CurrentWindow->Operators.pFirst; a; a = a->Item.pNext){ if (at == a->Type){ return 1; } }    return 0;}int laOperatorExists(const char* ID){    laOperatorType* at=laGetOperatorType(ID); if (!at) return 0;    return laOperatorExistsT(at);}int la_OperatorExists(laOperator *ac){    if (!ac) return 0;    laOperator *a;    for (a = MAIN.CurrentWindow->Operators.pFirst; a; a = a->Item.pNext){ if (ac == a){return 1;}}    return 0;}int la_UiOperatorExists(void *inst){    laOperator *a;    if (!inst) return 0;    for (a = MAIN.CurrentWindow->Operators.pFirst; a; a = a->Item.pNext){        if (((laUiItem *)a->Instance) == inst){            return 1;        }    }    for (a = MAIN.CurrentWindow->PendingOperators.pFirst; a; a = a->Item.pNext){        if (a->Instance == inst){            return 1;        }    }    return 0;}int la_OperatorPending(laOperator *target){    laOperator *a;    if (!target) return 0;    for (a = MAIN.CurrentWindow->PendingOperators.pFirst; a; a = a->Item.pNext){        if (a == target){            return 1;        }    }    return 0;}void laSetOperatorLocalizer(void *ToPanel){    MAIN.ToPanel = ToPanel;}void la_DestroyConfirmData(laConfirmData **cd);void *la_DestroyOperator(laOperator **a, laListHandle *Operators, int OnlyThisOne){    laOperator *ai = (*a);    laOperator *ac = ((*a)->Child);    void *Ret = 0;    if (!OnlyThisOne && ac && la_OperatorExists(ac) && !ac->Using && !ac->ModalOver){        la_DestroyOperator(&ac, Operators, OnlyThisOne);    }    if ((*a)->ConfirmData) la_DestroyConfirmData(&((*a)->ConfirmData));    if ((*a)->PP.LastPs){        memFree((*a)->PP.LastPs->p);        memFree((*a)->PP.LastPs);    }    if (laNonFixedPanelExists((*a)->OperatorPanel)){        la_SetPropMathcerContext((*a)->OperatorPanel);        MAIN.CurrentPanel = (*a)->OperatorPanel;        laDestroySinglePanel((*a)->OperatorPanel,0);    }    if ((*a)->CreatedThis) memFree((*a)->CreatedThis);    if ((*a)->ExtraInstructionsP) strDestroyStringSplitor(&(*a)->ExtraInstructionsP);    lstClearPointer(&(*a)->LocalUiLists);    if (Operators){        Ret = ai->Item.pNext;        if (la_OperatorPending((*a) /*->Instance*/)) lstRemoveItem(&MAIN.CurrentWindow->PendingOperators, *a);        else            lstRemoveItem(Operators, *a);        for (ai = Operators->pFirst; ai; ai = ai->Item.pNext){            if (ai->Child == (*a)) ai->Child = 0;        }    }    strSafeDestroy(&(*a)->RuntimeHint);    free(*a);    return Ret;}int laOperatorAvailable(char *ID, laPropPack *This, laStringSplitor *Instructions){    laOperatorType *at = hsh256FindItemSTR(&MAIN.OperatorTypeHash, la_OperatorTypeByID, ID);    if (!at) return 0;    if (!at->Check) return 1;    return (at->Check(This, Instructions));}int laOperatorAvailableP(laOperatorType *at, laPropPack *This, laStringSplitor *Instructions){    if (!at) return 0;    if (!at->Check) return 1;    return (at->Check(This, Instructions));}int laOperatorAvailablePSafe(laOperatorType *at, laPropPack *This, void *Real_FromInstance, laStringSplitor *Instructions){    laPropPack FakePP = {0};    laPropStep FakePs = {0};    if (!at) return 0;    if (!at->Check) return 1;    FakePP.LastPs = &FakePs;    FakePP.Go = FakePP.LastPs;    FakePP.LastPs->p = This->LastPs->p;    FakePP.LastPs->UseInstance = This->EndInstance;    FakePP.EndInstance = Real_FromInstance;    FakePP.LastIndex = This->LastIndex;    return (at->Check(&FakePP, Instructions));}int laOperatorAvailableSafe(char *ID, laPropPack *This, void *Real_FromInstance, laStringSplitor *Instructions){    laOperatorType *at = hsh256FindItemSTR(&MAIN.OperatorTypeHash, la_OperatorTypeByID, ID);    return laOperatorAvailablePSafe(at, This, Real_FromInstance, Instructions);}int laInvokeP(laOperator *From, laOperatorType *at, laEvent *e, laPropPack *This, char *args, char *args2){    laOperator *a, *f = From;    int rev;    if (!f && e&&e->Localized) return -1;    a = la_CreateOperator(at);    a->ToPanel = MAIN.ToPanel;    a->This = This;    a->ExtraInstructions = args;    strMakeInstructions(&a->ExtraInstructionsP, args);    strMakeInstructions(&a->ExtraInstructionsP, args2);    strMakeInstructions(&a->ExtraInstructionsP, at->ExtraInstructions);    if (!laOperatorAvailableP(at, This, a->ExtraInstructionsP)){        la_DestroyOperator(&a, 0, 0);        return LA_CANCELED;    }    lstGeneratePointerList(f ? &f->LocalUiLists : 0, 0, &a->LocalUiLists);    if (e&&!e->Localized && at->ExtraMark & LA_EXTRA_TO_PANEL){        laWindowToLocal(0, a->ToPanel, &e->x, &e->y);        e->Localized = 1;    }    if (e&&e->Localized){        if (!at->ExtraMark & LA_EXTRA_TO_PANEL){            laLocalToWindow(f, f->ToPanel, &e->x, &e->y);            e->Localized = 0;        }else{            laLocalToWindow(f, f->ToPanel, &e->x, &e->y);            laWindowToLocal(a, a->ToPanel, &e->x, &e->y);        }    }    if (From) f->Child = a;    a->Using = 1;    if (at->Init) at->Init(a);    rev = at->Invoke(a, e);    a->Using = 0;    if (rev & LA_FINISH){        a->StopNow = 1;  if(From)From->Child=0;        laConfirmSameDataIfAny(a); la_DestroyConfirmData(&MAIN.InvokeConfirmData); MAIN.InvokeConfirmData=a->NextConfirmData;    }    if (!a->StopNow && (rev&LA_BLOCK || rev&LA_PASS_ON)){        if(a->ModalOver){ lstPushItem(&MAIN.CurrentWindow->PendingOperators, a); }        else{ lstAppendItem(&MAIN.CurrentWindow->PendingOperators, a); }        a->State = rev;        a->PP.EndInstance = a->CustomData;        if (a->PP.LastPs) a->PP.LastPs->Type = U'.';    }else        la_DestroyOperator(&a, 0, 0);    return rev;}int laInvoke(laOperator *From, char *ID, laEvent *e, laPropPack *This, char *args, char *args2){    laOperatorType *at; laOperator *a, *f = From;    at = hsh256FindItemSTR(&MAIN.OperatorTypeHash, la_OperatorTypeByID, ID);    if (!at) return -1;    return laInvokeP(From,at,e,This,args,args2);}int laInvokePCreateThis(laOperator *From, laOperatorType *at, laEvent *e, laPropPack *OrigionalThis, void *FromInstance, char *args, char *args2){    laOperator *a, *f = From;    int rev;    laPropPack *created;    if (!f && e&&e->Localized || !OrigionalThis || !OrigionalThis->LastPs) return -1;    created = memAcquireSimple(sizeof(laPropPack));    created->LastPs = memAcquireSimple(sizeof(laPropStep));    created->Go = created->LastPs;    created->LastPs->p = OrigionalThis->LastPs->p;    created->LastPs->UseInstance = OrigionalThis->LastPs->UseInstance;    created->EndInstance = FromInstance;    created->LastIndex = OrigionalThis->LastIndex;    a = la_CreateOperator(at);    a->ToPanel = MAIN.ToPanel;    a->This = created;    a->CreatedThis = created;    a->ExtraInstructions = args;    strMakeInstructions(&a->ExtraInstructionsP, args);    strMakeInstructions(&a->ExtraInstructionsP, args2);    strMakeInstructions(&a->ExtraInstructionsP, at->ExtraInstructions);    if (!laOperatorAvailableP(at, created, a->ExtraInstructionsP)){        la_DestroyOperator(&a, 0, 0);        return LA_CANCELED;    }    lstGeneratePointerList(f ? &f->LocalUiLists : 0, 0, &a->LocalUiLists);    if (e&&!e->Localized && at->ExtraMark & LA_EXTRA_TO_PANEL) laWindowToLocal(0, a->ToPanel, &e->x, &e->y);    if (From) f->Child = a;    a->Using = 1;    if (at->Init) at->Init(a);    rev = at->Invoke(a, e);    a->Using = 0;    if (rev & LA_FINISH){        a->StopNow = 1; if(From)From->Child=0;        laConfirmSameDataIfAny(a); la_DestroyConfirmData(&MAIN.InvokeConfirmData); MAIN.InvokeConfirmData=a->NextConfirmData;    }    if (!a->StopNow && (rev&LA_BLOCK || rev&LA_PASS_ON)){        if(a->ModalOver){ lstPushItem(&MAIN.CurrentWindow->PendingOperators, a); }        else{ lstAppendItem(&MAIN.CurrentWindow->PendingOperators, a); }        a->State = rev;        a->PP.EndInstance = a->CustomData;    }else        la_DestroyOperator(&a, 0, 0);    return rev;}int laInvokeUiP(laOperator *From, laOperatorType *at, laEvent *e, void *inst, laListHandle *Locals, int IgnoreLocals){    laOperator *a, *f = From;    int rev;    if (!at || (la_UiOperatorExists(inst))){ return -1; }    a = la_CreateOperator(at);    a->Instance = inst;    a->ToPanel = MAIN.ToPanel;    if (!IgnoreLocals) lstGeneratePointerList(f ? &f->LocalUiLists : 0, Locals, &a->LocalUiLists);    if (From) f->Child = a;    a->Using = 1;    if (at->Init) at->Init(a);    rev = at->Invoke(a, e);    a->Using = 0;    if (rev & LA_FINISH){        a->StopNow = 1; if(From)From->Child=0;    }    if (rev & LA_BLOCK){        lstAppendItem(&MAIN.CurrentWindow->PendingOperators, a);        a->State = rev;    }else la_DestroyOperator(&a, 0, 0);    DEB = a;    return rev;}int laInvokeUi(laOperator *From, char *ID, laEvent *e, void *inst, laListHandle *Locals, int IgnoreLocals){    laOperatorType *at;    laOperator *a, *f = From;    if (la_UiOperatorExists(inst)) return -1;    at = hsh256FindItemSTR(&MAIN.OperatorTypeHash, la_OperatorTypeByID, ID); if (!at) return -1;    return laInvokeUiP(From,at,e,inst,Locals,IgnoreLocals);}void laRequestDelayEvent(real Seconds){    MAIN.DelayTriggered=0; MAIN.DelayStart=MAIN.TimeAccum; MAIN.DelayTime = Seconds; }int la_UiStillInService(void *UiInstance){    laOperator *ai, *dai; if(!MAIN.CurrentWindow) return 0;    for (ai = MAIN.CurrentWindow->Operators.pFirst; ai; ai = ai->Item.pNext){        if (ai->Instance == UiInstance) return 1;    }    return 0;}void la_StopUiOperatorService(void *UiInstance){    laOperator *ai, *dai, *NextAi;    if (!MAIN.CurrentWindow) return;    for (ai = MAIN.CurrentWindow->PendingOperators.pFirst; ai; ai = NextAi){        NextAi = ai->Item.pNext;        if (ai->Instance == UiInstance){            if (ai->Child){                la_StopUiOperatorService(ai->Child->Instance);                ai->Child = 0;            }            laOperator *dai = ai;            la_DestroyOperator(&dai, &MAIN.CurrentWindow->PendingOperators, 1);            continue;        }    }    for (ai = MAIN.CurrentWindow->Operators.pFirst; ai; ai = NextAi){        NextAi = ai->Item.pNext;        if (ai->Instance == UiInstance){            if (ai->Instance == ai->ToPanel){                //laHidePanelWithDissoveEffect(ai->ToPanel);                //ai->ToPanel->LaterDestroy = 1;            }            if (ai->Child && la_OperatorExists(ai->Child)){                la_StopUiOperatorService(ai->Child->Instance);                //ai->Child = 0;            }            if (!ai->Using){                laOperator *dai = ai;                la_DestroyOperator(&dai, &MAIN.CurrentWindow->Operators, 1);            }else                ai->StopNow = 1;        }    }}void la_StopAllOperators(){    laOperator *ai, *dai, *NextAi;    if (!MAIN.CurrentWindow) return;    for (ai = MAIN.CurrentWindow->PendingOperators.pFirst; ai; ai = NextAi){        NextAi = ai->Item.pNext;        NextAi = la_DestroyOperator(&ai, &MAIN.CurrentWindow->PendingOperators, 1);        continue;    }    for (ai = MAIN.CurrentWindow->Operators.pFirst; ai; ai = NextAi){        NextAi = ai->Item.pNext;        if (ai->ToPanel && ai->Instance == ai->ToPanel && !ai->ToPanel->IsMenuPanel){            laHidePanelWithDissoveEffect(ai->ToPanel);            ai->ToPanel->LaterDestroy = 1;        }        if (!ai->Using){            laOperator *dai = ai;            la_DestroyOperator(&dai, &MAIN.CurrentWindow->Operators, 1);        }else ai->StopNow = 1;    }}void la_DestroyConfirmData(laConfirmData **cd){    if((!cd)||!(*cd)) return;    if ((*cd)->CustomData && (*cd)->Destroy) (*cd)->Destroy((*cd)->CustomData);    if ((*cd)->StrData) free((*cd)->StrData);    FreeMem((*cd));    (*cd) = 0;}void laConfirmPointer(laOperator *a, void* Data,laPropContainer* PointerType, int mode){    laOperator *ai = a; laConfirmData *cd = CreateNew(laConfirmData);    cd->PointerData = Data; cd->Mode = mode; cd->PointerType=PointerType;    ai->NextConfirmData = cd; laRetriggerOperators();}void laConfirmInt(laOperator *a, int Data, int mode){    laOperator *ai = a;laConfirmData *cd = CreateNew(laConfirmData);    cd->IData = Data; cd->Mode = mode;    ai->NextConfirmData = cd; laRetriggerOperators();}void laConfirmFloat(laOperator *a, real Data, int mode){    laOperator *ai = a;laConfirmData *cd = CreateNew(laConfirmData);    cd->FData = Data; cd->Mode = mode;    ai->NextConfirmData = cd; laRetriggerOperators();}void laConfirmString(laOperator *a, char *Str, int mode){    laOperator *ai = a;    laConfirmData *cd = CreateNew(laConfirmData);    int len = strlen(Str);    char *buf = calloc(len + 1, sizeof(char));    strcpy(buf, Str);    cd->StrData = buf;    cd->Mode = mode;    cd->Destroy = free;    ai->NextConfirmData = cd;    laRetriggerOperators();}int laConfirmSameDataIfAny(laOperator *a){    laOperator *ai = a;    laConfirmData *cd;    char *buf = 0;    if (!ai->ConfirmData || ai->NextConfirmData) return 0;    cd = CreateNew(laConfirmData);    if (ai->ConfirmData->StrData){        int len = strlen(ai->ConfirmData->StrData);        buf = calloc(len + 1, sizeof(char));        strcpy(buf, ai->ConfirmData->StrData);    }    //cd->CustomData = cd->CustomData;    cd->IData = ai->ConfirmData->IData;    cd->FData = ai->ConfirmData->FData;    cd->PointerData = ai->ConfirmData->PointerData;    cd->PointerType = a->ConfirmData->PointerType;    cd->StrData = buf;    cd->Mode = ai->ConfirmData->Mode;    cd->Destroy = ai->ConfirmData->Destroy;    ai->NextConfirmData = cd;    laRetriggerOperators();    return 1;}void laConfirmUserData(laOperator *a, void *UserData, laConfirmDataDestroyFunc Destroy, int mode){    laOperator *ai = a;    laConfirmData *cd = CreateNew(laConfirmData);    cd->CustomData = UserData;    cd->Mode = mode;    cd->Destroy = Destroy;    ai->NextConfirmData = cd;    laRetriggerOperators();}int laGetConfirmMode(laOperator *a){    return ((laOperator *)a)->ConfirmData->Mode;}int laGetConfirmInt(laOperator *a){    laOperator *ai = a;    int rev = ai->ConfirmData->IData;    la_DestroyConfirmData(&ai->ConfirmData);    ai->ConfirmData = 0;    return rev;}real laGetConfirmFloat(laOperator *a){    laOperator *ai = a;    real rev = ai->ConfirmData->FData;    la_DestroyConfirmData(&ai->ConfirmData);    ai->ConfirmData = 0;    return rev;}void laGetConfirmString(laOperator *a, char *buf){    laOperator *ai = a;    strcpy(buf, ai->ConfirmData->StrData);    la_DestroyConfirmData(&ai->ConfirmData);    ai->ConfirmData = 0;}void *laGetConfirmUserData(laOperator *a){    laOperator *ai = a;    return ai->ConfirmData->CustomData;}void laFinalizeOperators(){    laOperatorType *at;    laListHandle *lst;    int i;    for (i = 0; i < 256; i++){        lst = &MAIN.OperatorTypeHash.Entries[i];        for (at = lst->pFirst; at; at = at->Item.pNext){            if (at->PC && at->PC->Props.pFirst){                lstAppendItem(&MAIN.PropContainers, at->PC);            }        }    }}//=================#ifdef __linux__static void la_RecordWacomMotions(XIRawEvent *event){    double *valuator = event->valuators.values;    int IsStylus=event->deviceid==MAIN.WacomDeviceStylus;    if(!IsStylus) MAIN.PointerIsEraser = 1; else MAIN.PointerIsEraser = 0;    //SYSWINDOW root_return, child_return;    //int root_x_return, root_y_return;    //int win_x_return, win_y_return;    //unsigned int mask_return;    //int retval = XQueryPointer(MAIN.dpy, RootWindow(MAIN.dpy,0), &root_return, &child_return,    //                            &root_x_return, &root_y_return,    //                            &win_x_return, &win_y_return,    //                            &mask_return);    //    //printf("root: x %d y %d\n", win_x_return, win_y_return);    if(XIMaskIsSet(event->valuators.mask, 2)){ if(IsStylus) MAIN.StylusPressure=valuator[2]/MAIN.StylusMaxPressure; else MAIN.EraserPressure=valuator[2]/MAIN.EraserMaxPressure; }    if(XIMaskIsSet(event->valuators.mask, 3) && XIMaskIsSet(event->valuators.mask, 4)){        real x=valuator[3],y=valuator[4];        real orientation=atan2(y,x); real deviation=sqrt(x*x+y*y); deviation=rad(deviation);        if(IsStylus){ MAIN.StylusOrientation=orientation;MAIN.StylusDeviation=deviation; }        else { MAIN.EraserOrientation=orientation;MAIN.EraserDeviation=deviation; }    }else{ MAIN.StylusDeviation=MAIN.StylusOrientation=MAIN.EraserDeviation=MAIN.EraserOrientation=0; }    if(XIMaskIsSet(event->valuators.mask, 5)){        real angle=valuator[5]; angle=rad((900-angle)/10*2-180); if(angle<0) angle+=TNS_PI*2; MAIN.StylusTwist=angle;        if(TNS_DOUBLE_CLOSE_ENOUGH(angle,TNS_PI)){ MAIN.StylusHasTwist=0; }else{ MAIN.StylusHasTwist=1; }    }else{ MAIN.StylusTwist=TNS_PI; MAIN.StylusHasTwist=0; }    MAIN.IsPen=1;}#endif#ifdef _WIN32#define PARAM_2_FROM(p) LOWORD(p),HIWORD(p)LRESULT CALLBACK LA_WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {    static uint32_t ch = 0; static int lead = 0;    static wchar_t buf[10] = { 0 }; int adv;    char mbuf[10] = { 0 }; uint32_t uchar=0;    short wheelmark = 0;    int  WheelDir = 0;    UINT32 pointerId; POINTER_INPUT_TYPE pointerType;    POINTER_PEN_INFO penInfo[128]; POINTER_TOUCH_INFO touchInfo; int peninfonum = 128;    POINT point;    PACKET pkt;    static POINT ptOld, ptNew;    static UINT prsOld, prsNew, vkey;    if (!hwnd) return DefWindowProc(hwnd, message, wparam, lparam);    switch (message) {    case WM_PAINT:        //SwapBuffers(GetDC(hwnd));        break;    case WM_MOUSEMOVE:        la_SendMouseEvent(hwnd, LA_MOUSEMOVE, PARAM_2_FROM(lparam));        MAIN.IsPen = 0;        break;    case WM_LBUTTONDOWN: la_SendMouseEvent(hwnd, LA_L_MOUSE_DOWN, PARAM_2_FROM(lparam)); break;    case WM_LBUTTONUP:   la_SendMouseEvent(hwnd, LA_L_MOUSE_UP, PARAM_2_FROM(lparam)); break;    case WM_RBUTTONDOWN: la_SendMouseEvent(hwnd, LA_R_MOUSE_DOWN, PARAM_2_FROM(lparam)); break;    case WM_RBUTTONUP:   la_SendMouseEvent(hwnd, LA_R_MOUSE_UP, PARAM_2_FROM(lparam)); break;    case WM_MBUTTONDOWN: la_SendMouseEvent(hwnd, LA_M_MOUSE_DOWN, PARAM_2_FROM(lparam)); break;    case WM_MBUTTONUP:   la_SendMouseEvent(hwnd, LA_M_MOUSE_UP, PARAM_2_FROM(lparam)); break;    case WM_MOUSEWHEEL:        POINT p; p.x=LOWORD(lparam); p.y=HIWORD(lparam); ScreenToClient(hwnd,&p);        if ((wheelmark = HIWORD(wparam)) > 0) WheelDir = LA_MOUSEUP;        else if ((wheelmark = HIWORD(wparam)) < 0) WheelDir = LA_MOUSEDOWN;        la_SendMouseEvent(hwnd, WheelDir|LA_KEY_MOUSE_SCROLL, p.x, p.y);        break;    case WT_PACKET:        if (!MAIN.InkOrWinTab) { break; /* Use Windows Ink. */ }        if (gpWTPacket((HCTX)lparam, wparam, &pkt)) {            MAIN.StylusPressure = (real)pkt.pkNormalPressure / MAIN.WinTabMaxPenPressure;            real angle = (real)pkt.pkOrientation.orAzimuth / 3600 * TNS_PI * 2 + TNS_PI / 2;            MAIN.StylusOrientation = angle; MAIN.StylusDeviation = rad((90.0f - (real)pkt.pkOrientation.orAltitude / 10.0f));            real tw = (real)pkt.pkOrientation.orTwist; tw = rad(tw / 10);            MAIN.StylusTwist = tw;            if(TNS_DOUBLE_CLOSE_ENOUGH(tw,TNS_PI)){ MAIN.StylusHasTwist=0; }else{ MAIN.StylusHasTwist=1; }            MAIN.EraserDeviation = MAIN.StylusDeviation; MAIN.EraserOrientation = MAIN.StylusOrientation;            MAIN.EraserPressure = MAIN.StylusPressure;            MAIN.IsPen = 1; MAIN.PointerIsEraser = ((pkt.pkStatus & TPS_INVERT) == TPS_INVERT);            point.x = pkt.pkX; point.y = pkt.pkY; ScreenToClient(hwnd, &point);            la_SendMouseEvent(hwnd, LA_MOUSEMOVE, point.x, point.y);        }        return 0; break;    case WM_SYSCOMMAND:        switch (wparam) {        case SC_MAXIMIZE:        case SC_RESTORE:            la_CommandResizeWindow(hwnd, 0, 0, LOWORD(lparam), HIWORD(lparam));            break;        case SC_KEYMENU:            return 0;        }        break;    case WM_SIZE:        if (wparam == SIZE_MINIMIZED) break;    case WM_MOVE: /* And size */        la_CommandResizeWindow(hwnd, 0, 0, LOWORD(lparam), HIWORD(lparam));        break;    case WM_SETCURSOR:        if(MAIN.CurrentCursor) return 1;        break;    case WM_POINTERDOWN:    case WM_POINTERUP:    case WM_POINTERUPDATE:        if (MAIN.InkOrWinTab) { break;/* Use WinTab. */ }        pointerId = GET_POINTERID_WPARAM(wparam);        pointerType = PT_POINTER;        if(!GetPointerType(pointerId, &pointerType)){            pointerType = PT_POINTER;        }        if(pointerType == PT_PEN){            if(GetPointerPenInfoHistory(pointerId, &peninfonum, penInfo)){                for (int i = peninfonum-1; i>=0; i--) {                    point.x = penInfo[i].pointerInfo.ptPixelLocation.x; point.y = penInfo[i].pointerInfo.ptPixelLocation.y;                    ScreenToClient(hwnd, &point);                    MAIN.IsPen = 1; MAIN.StylusPressure = (real)penInfo[i].pressure / 1024; MAIN.PointerIsEraser = 0;                    switch (penInfo[i].pointerInfo.ButtonChangeType) {                    case POINTER_CHANGE_FIRSTBUTTON_DOWN: la_SendMouseEvent(hwnd, LA_L_MOUSE_DOWN, point.x, point.y); break;                    case POINTER_CHANGE_FIRSTBUTTON_UP: la_SendMouseEvent(hwnd, LA_L_MOUSE_UP, point.x, point.y); break;                    case POINTER_CHANGE_SECONDBUTTON_DOWN: la_SendMouseEvent(hwnd, LA_M_MOUSE_DOWN, point.x, point.y); break;                    case POINTER_CHANGE_SECONDBUTTON_UP: la_SendMouseEvent(hwnd, LA_M_MOUSE_UP, point.x, point.y); break;                    case POINTER_CHANGE_THIRDBUTTON_DOWN: la_SendMouseEvent(hwnd, LA_R_MOUSE_DOWN, point.x, point.y); break;                    case POINTER_CHANGE_THIRDBUTTON_UP: la_SendMouseEvent(hwnd, LA_R_MOUSE_UP, point.x, point.y); break;                    }                    la_SendMouseEvent(hwnd, LA_MOUSEMOVE, point.x, point.y);                }            }            SkipPointerFrameMessages(pointerId);            return 0;        }        else if (pointerType == PT_TOUCH){            if (GetPointerTouchInfo(pointerId, &touchInfo)) {                point.x = touchInfo.pointerInfo.ptPixelLocation.x; point.y = touchInfo.pointerInfo.ptPixelLocation.y;                ScreenToClient(hwnd, &point);                MAIN.IsPen = 1; MAIN.StylusPressure = (real)touchInfo.pressure / 1024; MAIN.PointerIsEraser = 1;            }        }        break;    case WM_SYSKEYDOWN:        if (lparam & 0x40000000) break;        la_SendKeyboardEvent(hwnd, LA_KEY_DOWN, la_TranslateSpecialKey(wparam));        break;    case WM_KEYDOWN:        if (lparam & 0x40000000) break;        vkey = wparam;        la_SendKeyboardEvent(hwnd, LA_KEY_DOWN, la_TranslateSpecialKey(vkey));        break;    case WM_KEYUP:        la_SendKeyboardEvent(hwnd, LA_KEY_UP, la_TranslateSpecialKey(wparam));        break;    case WM_SYSKEYUP:        la_SendKeyboardEvent(hwnd, LA_KEY_UP, la_TranslateSpecialKey(wparam));        break;    case WM_UNICHAR:        la_SendInputEvent(hwnd, wparam);        break;    case WM_IME_CHAR:        la_SendInputEvent(hwnd, wparam);        return 0;    case WM_CHAR:        la_SendInputEvent(hwnd, wparam);        break;    case WM_SHOWWINDOW:        //SendCommandEvent(hwnd, EVT_WND_SIZE_FINISH);        break;    case WM_CLOSE:        if (!la_OnWindowDestroy(hwnd)) return 0; return 1;        break;    default:        return DefWindowProc(hwnd, message, wparam, lparam);    }    return DefWindowProc(hwnd, message, wparam, lparam);}LRESULT CALLBACK LA_ProgressWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam){    return DefWindowProc(hwnd, message, wparam, lparam);}#endifint la_UpdateOperatorHints(laWindow* w){    laSafeString* ss=0;    for(laOperator* o=w->Operators.pFirst;o;o=o->Item.pNext){        if(o->RuntimeHint&&o->RuntimeHint->Ptr){ strSafePrint(&ss, "%s | %s  ", o->Type->Name, o->RuntimeHint->Ptr);}    }    if((w->OperatorHints&&ss&&strSame(ss->Ptr,w->OperatorHints->Ptr))||(!w->OperatorHints&&!ss)){ //pass    }else{        if(ss){ strSafeSet(&w->OperatorHints,ss->Ptr); } else { strSafeDestroy(&w->OperatorHints); }        laNotifyUsers("la.windows.operator_hints");//printf("op hint\n");    }    strSafeDestroy(&ss);}int la_HandleSingleEvent(laEvent *e, laListHandle *Operators){    laOperator *a, *NextA = 0;    int Result = 0;    laConfirmData *ConfirmData = 0, *NextConfirmData = 0;    la_SendSignalsFromEvent(e);    if(MAIN.InputProcess){ MAIN.CurrentInputEvent=e; MAIN.InputProcess(e); MAIN.CurrentInputEvent=0; }    a = Operators->pFirst;    la_DestroyConfirmData(&MAIN.InvokeConfirmData);    while (1){        if (!a) break;        if (a->StopNow){            NextA = a->Item.pNext;            if (a->Type->Exit) a->Type->Exit(a, Result);            ConfirmData = a->NextConfirmData;            if (a->ConfirmData) la_DestroyConfirmData(&a->ConfirmData);            NextConfirmData = ConfirmData;            a->ConfirmData = 0;            a->NextConfirmData = 0;            la_DestroyOperator(&a, Operators, 0);            a = NextA;            if (a){                a->ConfirmData = NextConfirmData;            }            continue;        }        a->Using = 1;        la_SetPropMathcerContext(a->ToPanel);        laSetOperatorLocalizer(a->ToPanel);        MAIN.CurrentPanel = a->ToPanel;        if (a->Type->ExtraMark & LA_EXTRA_TO_PANEL){            laWindowToLocal(a, a->ToPanel, &e->x, &e->y);            e->Localized = 1;        }        if (a->State & LA_BLOCK){ Result = a->Type->Modal(a, e); }                if (a->Type->ExtraMark & LA_EXTRA_TO_PANEL){            laLocalToWindow(a, a->ToPanel, &e->x, &e->y);            e->Localized = 0;        }        la_SetPropMathcerContext(0);        laSetOperatorLocalizer(0);        MAIN.CurrentPanel = 0;        a->Using = 0;        if (Result & LA_PASS_ON){            laConfirmSameDataIfAny(a);            NextA = a->Item.pNext;        }else{            NextA = 0;            if (a->NextConfirmData){                la_DestroyConfirmData(&a->NextConfirmData);            }        }        ConfirmData = a->NextConfirmData;        if (a->ConfirmData) la_DestroyConfirmData(&a->ConfirmData);        NextConfirmData = ConfirmData;        a->ConfirmData = 0;        a->NextConfirmData = 0;        if (Result & LA_FINISH || Result == LA_CANCEL || (a->StopNow && a->Using == 0)){            if (a->Type->Exit) a->Type->Exit(a, Result);            la_DestroyOperator(&a, Operators, 0);            int found=0;            for(laOperator*iop=Operators->pFirst;iop;iop=iop->Item.pNext){ if(iop==NextA){found=1;} }            if(!found){ NextA=0; }            if(Result == LA_OPERATOR_CALLS_SHUTOFF){ return 0; }        }        a = NextA;        if (a){            a->ConfirmData = NextConfirmData;        }    }    return 1;}int la_HandleEvents(laWindow *w){    laEvent *e, *NextE;    laOperator *a;    laThreadNotifier *tn;    MAIN.CurrentWindow=w;    //laSpinLock(&MAIN.csNotifier);    while (tn = lstPopItem(&MAIN.ThreadNotifiers)){        //laSpinUnlock(&MAIN.csNotifier);        laNotifyUsers(tn->Path);        FreeMem(tn);        //if (MAIN.ThreadNotifiers.pFirst)            //laSpinLock(&MAIN.csNotifier);    }    //laSpinUnlock(&MAIN.csNotifier);    while (1){        if (MAIN.ReTriggerOperators) laSendOperatorTriggerEvent();        while (w->EventList.pFirst){            while (w->PendingOperators.pLast){                a = w->PendingOperators.pLast;                if (a->OperatorPanel){                    laSetOperatorLocalizer(a->OperatorPanel);                    if (a->OperatorPanel->Mode == LA_PANEL_FLOATING_TOP)                        laInvokeUi(a, "LA_modal_panel_operator", 0, a->OperatorPanel, 0, 1);                }                lstRemoveItem(&w->PendingOperators, a);                lstPushItem(&w->Operators, a);            }            e = lstPopItem(&w->EventList);            if (e && !w->Operators.pFirst){ laInvokeUi(0, "LA_window_operator", e, w, 0, 0); }            if (e) if(!la_HandleSingleEvent(e, &w->Operators)){ la_StopAllOperators(); memFree(e); return 0; } //EXIT            memFree(e);        }        MAIN.ControllerHasNewAxis = MAIN.ControllerHasNewKey = 0;        if (!MAIN.ReTriggerOperators) break;    }    la_UpdateOperatorHints(w);    return 1;}int la_AllowInput(uint32_t ch){    if(ch>=32 || ch==U'\n' || ch==U'\t' || ch==U'\b') return 1;    return 0;}int laCopyToClipboard(unsigned char * text){#ifdef __linux__	XEvent event; SYSWINDOW owner, window=MAIN.CurrentWindow->win;	XSetSelectionOwner(MAIN.dpy, MAIN.selection, window, 0);	if (XGetSelectionOwner (MAIN.dpy, MAIN.selection) != window) return 0;    strSafeSet(&MAIN.CopyPending, text);#endif}int la_ProcessSysMessage(){    int SendDelay = 0, SendIdle = 0;    if (!MAIN.DelayTriggered && MAIN.TimeAccum - MAIN.DelayStart > MAIN.DelayTime) SendDelay = 1;    if (!MAIN.IdleTriggered && MAIN.TimeAccum - MAIN.IdleStart > MAIN.IdleTime) SendIdle = 1;#ifdef __linux__    XEvent e;    int type;    int InputCount = 0, CharCount=0;    KeySym InputKeysym = 0;    Status InputStatus = 0;    laWindow* wnd ;    while(XPending(MAIN.dpy)){        XGenericEventCookie *cookie = &e.xcookie;        XNextEvent(MAIN.dpy, &e);        if (XFilterEvent(&e, None)) continue;        SendIdle=0; MAIN.IdleStart=MAIN.TimeAccum; MAIN.IdleTriggered=0;        if (cookie->type == GenericEvent && cookie->extension == MAIN.xi_opcode && XGetEventData(MAIN.dpy, cookie)){            if (cookie->evtype == XI_RawMotion) la_RecordWacomMotions(cookie->data);            XFreeEventData(MAIN.dpy, cookie); continue;        }                    switch(e.type){        case ConfigureNotify:            la_CommandResizeWindow(e.xconfigure.window, e.xconfigure.x, e.xconfigure.y, e.xconfigure.width, e.xconfigure.height);            break;        case Expose:            wnd = lstFindItem(e.xexpose.window, la_IsThisSysWindow, &MAIN.Windows);            if(!wnd) break;            laRefreshWindow(wnd);            break;        case MotionNotify:            la_SendMouseEvent(e.xmotion.window, LA_MOUSEMOVE, e.xmotion.x,e.xmotion.y);            MAIN.IsPen=0;            break;        case ButtonPress:            type=LA_MOUSEDOWN;            if(e.xbutton.button==1){type|=LA_KEY_MOUSE_LEFT;}            elif(e.xbutton.button==2){type|=LA_KEY_MOUSE_MIDDLE;}            elif(e.xbutton.button==3){type|=LA_KEY_MOUSE_RIGHT;}            elif(e.xbutton.button==4){type=LA_MOUSEUP|LA_KEY_MOUSE_SCROLL;}            elif(e.xbutton.button==5){type=LA_MOUSEDOWN|LA_KEY_MOUSE_SCROLL;}            la_SendMouseEvent(e.xbutton.window, type, e.xbutton.x,e.xbutton.y);            MAIN.IsPen=0;            break;        case ButtonRelease:            type=LA_MOUSEUP;            if(e.xbutton.button==1){type|=LA_KEY_MOUSE_LEFT;}            elif(e.xbutton.button==2){type|=LA_KEY_MOUSE_MIDDLE;}            elif(e.xbutton.button==3){type|=LA_KEY_MOUSE_RIGHT;}            la_SendMouseEvent(e.xbutton.window, type, e.xbutton.x,e.xbutton.y);            MAIN.IsPen=0;            break;        case KeyPress:                InputCount=Xutf8LookupString(MAIN.ic, (XKeyPressedEvent*)&e, MAIN.InputBuf, MAIN.InputBufMax, &InputKeysym, &InputStatus);                MAIN.InputBuf[InputCount]=0;                if (InputStatus==XBufferOverflow)  printf("XInputBufferOverflow\n");                if (InputStatus == XLookupKeySym || InputStatus == XLookupBoth) { /*printf("status: %d\n", InputStatus);*/ }            if (InputCount){ MAIN.InputBuf[InputCount]=0; } strToUnicode(MAIN.InputBufU,MAIN.InputBuf); int UCount=strlenU(MAIN.InputBufU);            for(int i=0;i<UCount;i++){ if(la_AllowInput(MAIN.InputBufU[i])) la_SendInputEvent(e.xkey.window, MAIN.InputBufU[i]); }            if(InputKeysym=XkbKeycodeToKeysym(e.xkey.display, e.xkey.keycode, 0, 0)){#ifdef DEBUG                printf("pressed KEY: %d\n", (int)InputKeysym);#endif                la_SendKeyboardEvent(e.xkey.window, LA_KEY_DOWN, la_TranslateSpecialKey(InputKeysym));            }            break;        case KeyRelease:            if(InputKeysym=XkbKeycodeToKeysym(e.xkey.display, e.xkey.keycode, 0, 0)){                la_SendKeyboardEvent(e.xkey.window, LA_KEY_UP, la_TranslateSpecialKey(InputKeysym));            }        case ClientMessage:            if(e.xclient.data.l[0]==MAIN.MsgDelWindow){                if(la_OnWindowDestroy(e.xclient.window)){ return 0; }            }            break;        case SelectionNotify:            if(e.xselection.selection != MAIN.bufid) continue;            if (e.xselection.property){                char *result; unsigned long ressize, restail; int resbits; Atom fmtid;                XGetWindowProperty(MAIN.dpy, MAIN.CurrentWindow->win, MAIN.propid, 0, LONG_MAX/4, False, AnyPropertyType,                &fmtid, &resbits, &ressize, &restail, (unsigned char**)&result);                if (fmtid == MAIN.incrid) logPrintNew("Pasted buffer is too large and INCR reading is not implemented yet.\n");                else if(result) {                    arrEnsureLength(&MAIN.InputBufU, strlen(result), &MAIN.InputBufUMax, sizeof(uint32_t));                    strToUnicode(MAIN.InputBufU,result); int UCount=strlenU(MAIN.InputBufU);                    for(int i=0;i<UCount;i++){ if(la_AllowInput(MAIN.InputBufU[i])) la_SendInputEvent(e.xkey.window, MAIN.InputBufU[i]); }                }                XFree(result);                return True;            }        case SelectionRequest:            if(!MAIN.CopyPending){ break; }            char* text=MAIN.CopyPending->Ptr; int size=strlen(text);			if (e.xselectionrequest.selection != MAIN.selection) break;			XSelectionRequestEvent * xsr = &e.xselectionrequest;			XSelectionEvent ev = {0};			int R = 0;			ev.type = SelectionNotify, ev.display = xsr->display, ev.requestor = xsr->requestor,			ev.selection = xsr->selection, ev.time = xsr->time, ev.target = xsr->target, ev.property = xsr->property;			if (ev.target == MAIN.targets_atom) R = XChangeProperty (ev.display, ev.requestor, ev.property, XA_ATOM, 32,					PropModeReplace, (unsigned char*)&MAIN.UTF8, 1);			else if (ev.target == XA_STRING || ev.target == MAIN.text_atom) 				R = XChangeProperty(ev.display, ev.requestor, ev.property, XA_STRING, 8, PropModeReplace, text, size);			else if (ev.target == MAIN.UTF8)				R = XChangeProperty(ev.display, ev.requestor, ev.property, MAIN.UTF8, 8, PropModeReplace, text, size);			else ev.property = None;			if ((R & 2) == 0) XSendEvent (MAIN.dpy, ev.requestor, 0, 0, (XEvent *)&ev);			break;        case SelectionClear:			break;        default:            break;        }    }#endif //linux#ifdef _WIN32    MSG msg; int Processed = 0;    if (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE) != 0) Processed = 1;    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {        if (msg.wParam == VK_PROCESSKEY) {            msg.wParam = ImmGetVirtualKey(msg.hwnd);        }        TranslateMessage(&msg); DispatchMessage(&msg);        SendIdle = 0; MAIN.IdleStart = MAIN.TimeAccum; MAIN.IdleTriggered = 0;    };    if(!MAIN.Windows.pFirst){ return 0; }#endif    for(laWindow* w=MAIN.Windows.pFirst;w;w=w->Item.pNext){        if(SendDelay) { la_SendTimerEvent(w->win, LA_TIME_DELAY); MAIN.DelayTriggered=1; }        if(SendIdle) { la_SendTimerEvent(w->win, LA_TIME_IDLE);  MAIN.IdleTriggered=1; }    }    return 1;};void la_PrintOperatorStack(){    laWindow *w = MAIN.CurrentWindow;    laOperator *a;    printf("\n");    for (a = w->Operators.pFirst; a; a = a->Item.pNext){        printf("OP [%-25s] For [0x%08x]  Child[%-25s][0x%08x]\n",               a->Type->Identifier, a->Instance,               (a->Child ? a->Child->Type->Identifier : ""), a->Child);    }}void la_DrawWindow(laWindow *w){    if(!w->Redraw) return; w->Redraw=0; w->RedrawTouched=1;    MAIN.CurrentWindow = w;    la_WindowDefDraw(w, 0);}int laFinalize(){    if(!laValidateProperties()){ laShutoff(0); return 0; }        laUiTemplate* uit;    while(uit=lstPopItem(&MAIN.InitPanelTemplates)) lstAppendItem(&MAIN.PanelTemplates,uit);    return 1;}void la_PreFrame(){    if(MAIN.PreFrame){ MAIN.PreFrame(); }    la_AnimationPreFrame();    if(MAIN.InitArgs.HasAudio) la_AudioPreFrame();}void la_PostFrame(){    laPanel* p; while(p=lstPopPointer(&MAIN.DeferredRedrawList)){ laRedrawPanel(p); }    if(MAIN.PostFrame){ MAIN.PostFrame(); }}void laMainLoop(){    laWindow *w = MAIN.Windows.pFirst, *NextW;    laTimeRecorder FrameStartTime, FrameEndTime;    time_t t1, t2;    real TimeInterval, Pause, TimeAccum = 0, FrameInterval;    static int a = 0;    if(!laFinalize()) return;    laSetWindowCursor(LA_ARROW);    MAIN.DelayTriggered=1;    while (1){        laRecordTime(&FrameStartTime);        la_PreFrame();        if(!la_ProcessSysMessage()){ return; }        la_UpdateControllerStatus();        if(MAIN.GraphNeedsRebuild){ MAIN.GraphNeedsRebuild = 0; }        for (w=MAIN.Windows.pFirst;w;w = NextW){            NextW = w->Item.pNext;            if(!la_HandleEvents(w)){ laShutoff(1); return; }        }        if(MAIN.PreDraw){ MAIN.PreDraw(); }        for(w=MAIN.Windows.pFirst;w;w=w->Item.pNext){            tnsSwitchToCurrentWindowContext(w); la_SetupWindowGLStates(w);            if(MAIN.GLDebugNeedsUpdate){                la_SetCurrentGLContextDebug();            }            la_DrawWindow(w);        }        for(w=MAIN.Windows.pFirst;w;w=w->Item.pNext){            if(!w->RedrawTouched) continue; w->RedrawTouched=0;#ifdef __linux__    #ifdef LA_USE_GLES            eglSwapBuffers(MAIN.egl_dpy, w->egl_surf);    #else            glXSwapBuffers(MAIN.dpy, w->win); //XSync(MAIN.dpy,0);    #endif#endif#ifdef _WIN32            SwapBuffers(w->hdc);#endif        }        MAIN.GLDebugNeedsUpdate=0;        la_PostFrame();        //t2 = clock();        laRecordTime(&FrameEndTime);        TimeInterval = laTimeElapsedSecondsf(&FrameEndTime, &FrameStartTime);        Pause = (1.0 / MAIN.TopFramerate - TimeInterval);        if (Pause > 0){            int us = Pause * 1000000.0;            usleep(us);        }        MAIN.TimeAccum += (MAIN.LastFrameTime = Pause+TimeInterval);        //FrameInterval = 1.0 / MAIN.Animation.FrameRate;        la_AnimationPostFrame();    }}#ifdef LA_ANDROIDvoid android_main(struct android_app *app){    char arg0[] = "lagui";     // NOTE: argv[] are mutable    CORE.Android.app = app;    // NOTE: Return from main is ignored    (void)main(1, (char *[]) { arg0, NULL });    // Request to end the native activity    ANativeActivity_finish(app->activity);    // Android ALooper_pollAll() variables    int pollResult = 0;    int pollEvents = 0;    // Waiting for application events before complete finishing    while (!app->destroyRequested)    {        while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void **)&CORE.Android.source)) >= 0)        {            if (CORE.Android.source != NULL) CORE.Android.source->process(app, CORE.Android.source);        }    }}#endif //android
 |