weditor.pas 242 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556
  1. {
  2. This file is part of the Free Pascal Integrated Development Environment
  3. Copyright (c) 1998 by Berczi Gabor
  4. Code editor template objects
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$I globdir.inc}
  12. unit WEditor;
  13. {$ifdef cpullvm}
  14. {$modeswitch nestedprocvars}
  15. {$endif}
  16. interface
  17. {tes}
  18. uses
  19. Dos,Objects,Drivers,Views,Dialogs,Menus,Stddlg,
  20. FVConsts,
  21. WUtils,WViews;
  22. const
  23. cmFileNameChanged = 51234;
  24. cmASCIIChar = 51235;
  25. cmClearLineHighlights = 51236;
  26. cmSaveCancelled = 51237;
  27. cmBreakLine = 51238;
  28. cmSelStart = 51239;
  29. cmSelEnd = 51240;
  30. cmLastCursorPos = 51241;
  31. cmIndentBlock = 51242;
  32. cmUnIndentBlock = 51243;
  33. cmSelectLine = 51244;
  34. cmWriteBlock = 51245;
  35. cmReadBlock = 51246;
  36. cmPrintBlock = 51247;
  37. cmResetDebuggerRow = 51248;
  38. cmAddChar = 51249;
  39. cmExpandCodeTemplate = 51250;
  40. cmUpperCase = 51251;
  41. cmLowerCase = 51252;
  42. cmWindowStart = 51253;
  43. cmWindowEnd = 51254;
  44. cmFindMatchingDelimiter= 51255;
  45. cmFindMatchingDelimiterBack=51256;
  46. cmActivateMenu = 51257;
  47. cmWordLowerCase = 51258;
  48. cmWordUpperCase = 51259;
  49. cmOpenAtCursor = 51260;
  50. cmBrowseAtCursor = 51261;
  51. cmInsertOptions = 51262;
  52. cmToggleCase = 51263;
  53. cmCreateFold = 51264;
  54. cmToggleFold = 51265;
  55. cmCollapseFold = 51266;
  56. cmExpandFold = 51267;
  57. cmDelToEndOfWord = 51268;
  58. cmInputLineLen = 51269;
  59. cmScrollOneUp = 51270;
  60. cmScrollOneDown = 51271;
  61. EditorTextBufSize = 32768;
  62. {$if sizeof(sw_astring)>8}
  63. MaxLineLength = 255; {Shortstring line length}
  64. {$else}
  65. MaxLineLength = 9997; {AnsiString max visible line}
  66. {$endif}
  67. MaxLineCount = 2000000;
  68. CodeTemplateCursorChar = '|'; { AnsiChar to signal cursor pos in templates }
  69. efBackupFiles = $00000001;
  70. efInsertMode = $00000002;
  71. efAutoIndent = $00000004;
  72. efUseTabCharacters = $00000008;
  73. efBackSpaceUnindents = $00000010;
  74. efPersistentBlocks = $00000020;
  75. efSyntaxHighlight = $00000040;
  76. efBlockInsCursor = $00000080;
  77. efVerticalBlocks = $00000100;
  78. efHighlightColumn = $00000200;
  79. efHighlightRow = $00000400;
  80. efAutoBrackets = $00000800;
  81. efExpandAllTabs = $00001000;
  82. efKeepTrailingSpaces = $00002000;
  83. efCodeComplete = $00004000;
  84. efFolds = $00008000;
  85. efNoIndent = $00010000;
  86. efKeepLineAttr = $00020000;
  87. efOverwriteBlocks = $00040000;
  88. efShowIndent = $00080000;
  89. efEnhWordRightLeft = $00100000;
  90. efStoreContent = $80000000;
  91. attrAsm = 1;
  92. attrComment = 2;
  93. attrForceFull = 128;
  94. attrAll = attrAsm+attrComment;
  95. edOutOfMemory = 0;
  96. edReadError = 1;
  97. edWriteError = 2;
  98. edCreateError = 3;
  99. edSaveModify = 4;
  100. edSaveUntitled = 5;
  101. edSaveAs = 6;
  102. edFind = 7;
  103. edSearchFailed = 8;
  104. edReplace = 9;
  105. edReplacePrompt = 10;
  106. edTooManyLines = 11;
  107. edGotoLine = 12;
  108. edReplaceFile = 13;
  109. edWriteBlock = 14;
  110. edReadBlock = 15;
  111. edFileOnDiskChanged = 16;
  112. edChangedOnloading = 17;
  113. edSaveError = 18;
  114. edReloadDiskmodifiedFile = 19;
  115. edReloadDiskAndIDEModifiedFile = 20;
  116. ffmOptions = $0007; ffsOptions = 0;
  117. ffmDirection = $0008; ffsDirection = 3;
  118. ffmScope = $0010; ffsScope = 4;
  119. ffmOrigin = $0020; ffsOrigin = 5;
  120. ffDoReplace = $0040;
  121. ffReplaceAll = $0080;
  122. ffCaseSensitive = $0001;
  123. ffWholeWordsOnly = $0002;
  124. ffPromptOnReplace = $0004;
  125. ffForward = $0000;
  126. ffBackward = $0008;
  127. ffGlobal = $0000;
  128. ffSelectedText = $0010;
  129. ffFromCursor = $0000;
  130. ffEntireScope = $0020;
  131. {$ifdef TEST_REGEXP}
  132. ffUseRegExp = $0100;
  133. ffmUseRegExpFind = $0004;
  134. ffmOptionsFind = $0003;
  135. ffsUseRegExpFind = 8 - 2;
  136. ffmUseRegExpReplace = $0008;
  137. ffsUseRegExpReplace = 8 - 3;
  138. {$endif TEST_REGEXP}
  139. coTextColor = 0;
  140. coWhiteSpaceColor = 1;
  141. coCommentColor = 2;
  142. coReservedWordColor = 3;
  143. coIdentifierColor = 4;
  144. coStringColor = 5;
  145. coNumberColor = 6;
  146. coAssemblerColor = 7;
  147. coSymbolColor = 8;
  148. coDirectiveColor = 9;
  149. coHexNumberColor = 10;
  150. coTabColor = 11;
  151. coAsmReservedColor = 12;
  152. coBreakColor = 13;
  153. coFirstColor = 0;
  154. coLastColor = coBreakColor;
  155. lfBreakpoint = $0001;
  156. lfHighlightRow = $0002;
  157. lfDebuggerRow = $0004;
  158. lfSpecialRow = $0008;
  159. eaMoveCursor = 1;
  160. eaInsertLine = 2;
  161. eaInsertText = 3;
  162. eaDeleteLine = 4;
  163. eaDeleteText = 5;
  164. eaSelectionChanged = 6;
  165. eaCut = 7;
  166. eaPaste = 8;
  167. eaPasteWin = 9;
  168. eaDelChar = 10;
  169. eaClear = 11;
  170. eaCopyBlock = 12;
  171. eaMoveBlock = 13;
  172. eaDelBlock = 14;
  173. eaReadBlock = 15;
  174. eaIndentBlock = 16;
  175. eaUnindentBlock = 17;
  176. eaOverwriteText = 18;
  177. eaUpperCase = 19;
  178. eaLowerCase = 20;
  179. eaToggleCase = 21;
  180. eaCommentSel = 22;
  181. eaUnCommentSel = 23;
  182. eaDummy = 24;
  183. LastAction = eaDummy;
  184. ActionString : array [0..LastAction-1] of string[14] =
  185. ('','Move','InsLine','InsText','DelLine','DelText',
  186. 'SelChange','Cut','Paste','PasteWin','DelChar','Clear',
  187. 'CopyBlock','MoveBlock','DelBlock',
  188. 'ReadBlock','IndentBlock','UnindentBlock','Overwrite',
  189. 'UpperCase','LowerCase','ToggleCase',
  190. 'CommentBlock','UnCommentBlock');
  191. CIndicator = #2#3#1;
  192. CEditor = #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48#49#50;
  193. TAB = #9;
  194. FindStrSize = 79;
  195. type
  196. Tcentre = (do_not_centre,do_centre);
  197. PCustomCodeEditor = ^TCustomCodeEditor;
  198. PEditorLineInfo = ^TEditorLineInfo;
  199. PFoldCollection = ^TFoldCollection;
  200. PFold = ^TFold;
  201. TFold = object(TObject)
  202. constructor Init(AEditor: PCustomCodeEditor; AParentFold: PFold; ACollapsed: boolean);
  203. procedure AddReference(P: PObject);
  204. procedure RemoveReference(P: PObject);
  205. procedure AddLineReference(Line: PEditorLineInfo);
  206. procedure RemoveLineReference(Line: PEditorLineInfo);
  207. procedure AddChildReference(Fold: PFold);
  208. procedure RemoveChildReference(Fold: PFold);
  209. function CanDispose: boolean;
  210. function IsCollapsed: boolean;
  211. function IsParent(AFold: PFold): boolean;
  212. function GetLineCount: sw_integer;
  213. procedure Collapse(ACollapse: boolean);
  214. procedure Changed;
  215. function GetLevel: sw_integer;
  216. destructor Done; virtual;
  217. public
  218. ParentFold: PFold;
  219. Collapsed_: boolean;
  220. ReferenceCount: sw_integer;
  221. Editor: PCustomCodeEditor;
  222. LineCount_: sw_integer;
  223. Childs: PFoldCollection;
  224. end;
  225. TFoldCollection = object(TCollection)
  226. function At(Index: sw_Integer): PFold;
  227. end;
  228. PEditorBookMark = ^TEditorBookMark;
  229. TEditorBookMark = packed record {we save bookmarks in *.dsk file, so packed record it is}
  230. Valid : Boolean;
  231. Pos : TPoint;
  232. end;
  233. PEditorBookMarkCollection = ^TEditorBookMarkCollection;
  234. TEditorBookMarkCollection = object(TCollection)
  235. function At(Index: sw_Integer): PEditorBookMark;
  236. end;
  237. TEditorLineInfo = object(TObject)
  238. Editor: PCustomCodeEditor;
  239. {$if sizeof(sw_astring)>8}
  240. Format : PString;
  241. {$else}
  242. Format : Sw_AString;
  243. {$endif}
  244. BeginsWithMultiLineStringSuffixLen,
  245. EndsWithMultiLineStringSuffixLen : Sw_Word;
  246. BeginsWithString,
  247. EndsWithString : boolean;
  248. BeginsWithAsm,
  249. EndsWithAsm : boolean;
  250. BeginsWithComment,
  251. EndsInSingleLineComment,
  252. EndsWithComment : boolean;
  253. BeginsWithDirective,
  254. EndsWithDirective : boolean;
  255. BeginCommentType,EndCommentType : byte;
  256. BeginCommentDepth,EndCommentDepth : sw_integer;
  257. BeginNestedComments,EndNestedComments : byte;
  258. Fold: PFold;
  259. BookMarks: PEditorBookMarkCollection;
  260. constructor Init(AEditor: PCustomCodeEditor);
  261. destructor Done; virtual;
  262. function GetFormat: sw_astring;
  263. procedure SetFormat(const AFormat: sw_astring);
  264. procedure SetFold(AFold: PFold);
  265. procedure InsertMark(Mark:PEditorBookMark); virtual;
  266. procedure DeleteMark(Mark:PEditorBookMark); virtual;
  267. function MarkCount:Sw_integer; virtual;
  268. function GetMark(Index:Sw_integer):PEditorBookMark; virtual;
  269. procedure AdjustMark(APosX,Adjustment:Sw_integer); virtual;
  270. { Syntax information is now generated separately for each editor instance.
  271. This is not necessary for a one-language IDE, but this unit contains
  272. a _generic_ editor object, which should be (and is) as flexible as
  273. possible.
  274. The overhead caused by generating the same syntax info for ex.
  275. twice isn't so much... - Gabor }
  276. end;
  277. PEditorLineInfoCollection = ^TEditorLineInfoCollection;
  278. TEditorLineInfoCollection = object(TCollection)
  279. function At(Index: sw_Integer): PEditorLineInfo;
  280. end;
  281. PCustomLine = ^TCustomLine;
  282. TCustomLine = object(TObject)
  283. constructor Init(const AText: sw_AString; AFlags: longint);
  284. {a}function GetText: sw_AString; virtual;
  285. {a}procedure SetText(const AText: sw_AString); virtual;
  286. {a}function GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo; virtual;
  287. {a}function GetFlags: longint; virtual;
  288. {a}procedure SetFlags(AFlags: longint); virtual;
  289. function IsFlagSet(AFlag: longint): boolean; {$ifdef USEINLINE}inline;{$endif}
  290. procedure SetFlagState(AFlag: longint; ASet: boolean);
  291. procedure InsertMark(Editor: PCustomCodeEditor; Mark: PEditorBookMark); virtual;
  292. procedure DeleteMark(Editor: PCustomCodeEditor; Mark: PEditorBookMark); virtual;
  293. function MarkCount(Editor: PCustomCodeEditor):Sw_integer; virtual;
  294. function GetMark(Editor: PCustomCodeEditor; Index: Sw_integer):PEditorBookMark; virtual;
  295. procedure AdjustMark(Editor: PCustomCodeEditor; APosX,Adjustment: Sw_integer); virtual;
  296. destructor Done; virtual;
  297. public { internal use only! }
  298. {a}procedure AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor); virtual;
  299. {a}procedure RemoveEditorInfo(AEditor: PCustomCodeEditor); virtual;
  300. end;
  301. PLineCollection = ^TLineCollection;
  302. TLineCollection = object(TCollection)
  303. function At(Index: sw_Integer): PCustomLine;
  304. end;
  305. PEditorAction = ^TEditorAction;
  306. TEditorAction = object(TObject)
  307. StartPos : TPoint;
  308. EndPos : TPoint;
  309. {$if sizeof(sw_astring)>8}
  310. Text : PString;
  311. {$else}
  312. Text : Sw_AString;
  313. {$endif}
  314. ActionCount : longint;
  315. Flags : longint;
  316. Action : byte;
  317. IsGrouped : boolean;
  318. TimeStamp : longint; { this is needed to keep track of line number &
  319. position changes (for ex. for symbol browser)
  320. the line&pos references (eg. symbol info) should
  321. also contain such a timestamp. this will enable
  322. to determine which changes have been made since
  323. storage of the information and thus calculate
  324. the (probably) changed line & position information,
  325. so, we can still jump to the right position in the
  326. editor even when it is heavily modified - Gabor }
  327. constructor init(act:byte; StartP,EndP:TPoint;Txt:Sw_AString;AFlags : longint);
  328. constructor init_group(act:byte);
  329. function is_grouped_action : boolean;
  330. function GetText : sw_astring;
  331. procedure SetText(AText : sw_astring);
  332. destructor done; virtual;
  333. end;
  334. PEditorActionCollection = ^TEditorActionCollection;
  335. TEditorActionCollection = object(TCollection)
  336. CurrentGroupedAction : PEditorAction;
  337. GroupLevel : longint;
  338. function At(Idx : sw_integer) : PEditorAction;
  339. end;
  340. TSpecSymbolClass =
  341. (ssCommentPrefix,ssCommentSingleLinePrefix,ssCommentSuffix,ssStringPrefix,ssStringSuffix,
  342. ssStringMultiLinePrefix,ssStringMultiLineSuffix,
  343. ssDirectivePrefix{,ssDirectiveSuffix},ssAsmPrefix,ssAsmSuffix);
  344. TCompleteState = (csInactive,csOffering,csDenied);
  345. PEditorBinding = ^TEditorBinding;
  346. PEditorBindingCollection = ^TEditorBindingCollection;
  347. TEditorBindingCollection = object(TCollection)
  348. function At(Index: sw_Integer): PEditorBinding;
  349. end;
  350. TEditorBinding = object(TObject)
  351. Editor : PCustomCodeEditor;
  352. constructor Init(AEditor: PCustomCodeEditor);
  353. destructor Done; virtual;
  354. end;
  355. PCustomCodeEditorCore = ^TCustomCodeEditorCore;
  356. TCustomCodeEditorCore = object(TObject)
  357. protected
  358. Bindings : PEditorBindingCollection;
  359. LockFlag : sw_integer;
  360. ChangedLine : sw_integer;
  361. ContentsChangedCalled : boolean;
  362. LimitsChangedCalled : boolean;
  363. ModifiedChangedCalled : boolean;
  364. TabSizeChangedCalled : boolean;
  365. StoreUndoChangedCalled : boolean;
  366. {$ifdef TEST_PARTIAL_SYNTAX}
  367. LastSyntaxedLine : sw_integer;
  368. SyntaxComplete : boolean;
  369. {$endif TEST_PARTIAL_SYNTAX}
  370. public
  371. constructor Init;
  372. procedure BindEditor(AEditor: PCustomCodeEditor);
  373. procedure UnBindEditor(AEditor: PCustomCodeEditor);
  374. function IsEditorBound(AEditor: PCustomCodeEditor): boolean;
  375. function GetBindingCount: sw_integer;
  376. function GetBindingIndex(AEditor: PCustomCodeEditor): sw_integer;
  377. function SearchBinding(AEditor: PCustomCodeEditor): PEditorBinding;
  378. function CanDispose: boolean;
  379. destructor Done; virtual;
  380. public
  381. {a}function GetModified: boolean; virtual;
  382. function GetChangedLine: sw_integer;
  383. {a}procedure SetModified(AModified: boolean); virtual;
  384. {a}function GetStoreUndo: boolean; virtual;
  385. {a}procedure SetStoreUndo(AStore: boolean); virtual;
  386. {a}function GetSyntaxCompleted: boolean; virtual;
  387. {a}procedure SetSyntaxCompleted(SC: boolean); virtual;
  388. {a}function GetTabSize: integer; virtual;
  389. {a}procedure SetTabSize(ATabSize: integer); virtual;
  390. {a}function GetIndentSize: integer; virtual;
  391. {a}procedure SetIndentSize(AIndentSize: integer); virtual;
  392. function IsClipboard: Boolean;
  393. public
  394. { Notifications }
  395. procedure BindingsChanged;
  396. procedure ContentsChanged;
  397. procedure LimitsChanged;
  398. procedure ModifiedChanged;
  399. procedure TabSizeChanged;
  400. procedure StoreUndoChanged;
  401. {a}procedure DoContentsChanged; virtual;
  402. {a}procedure DoLimitsChanged; virtual;
  403. {a}procedure DoModifiedChanged; virtual;
  404. {a}procedure DoTabSizeChanged; virtual;
  405. {a}procedure DoStoreUndoChanged; virtual;
  406. {a}procedure DoSyntaxStateChanged; virtual;
  407. function GetLastVisibleLine : sw_integer;
  408. public
  409. { Storage }
  410. function LoadFromStream(Editor: PCustomCodeEditor; Stream: PFastBufStream): boolean; virtual;
  411. function SaveToStream(Editor: PCustomCodeEditor; Stream: PStream): boolean; virtual;
  412. function SaveAreaToStream(Editor: PCustomCodeEditor; Stream: PStream; StartP,EndP: TPoint): boolean; virtual;
  413. protected
  414. { Text & info storage abstraction }
  415. {a}procedure ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean); virtual;
  416. {a}procedure IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:sw_astring); virtual;
  417. {a}function IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): sw_astring; virtual;
  418. {a}procedure ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: sw_astring); virtual;
  419. public
  420. { Text & info storage abstraction }
  421. function CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
  422. function LinePosToCharIdx(Line,X: sw_integer): sw_integer;
  423. {a}function GetLineCount: sw_integer; virtual;
  424. {a}function GetLine(LineNo: sw_integer): PCustomLine; virtual;
  425. {a}function GetLineText(LineNo: sw_integer): sw_AString; virtual;
  426. {a}procedure SetDisplayText(I: sw_integer;const S: sw_astring); virtual;
  427. {a}function GetDisplayText(I: sw_integer): sw_astring; virtual;
  428. {a}procedure SetLineText(I: sw_integer;const S: sw_AString); virtual;
  429. procedure GetDisplayTextFormat(Editor: PCustomCodeEditor; I: sw_integer;var DT,DF:sw_astring); virtual;
  430. function GetLineFormat(Editor: PCustomCodeEditor; I: sw_integer): sw_astring; virtual;
  431. procedure SetLineFormat(Editor: PCustomCodeEditor; I: sw_integer;const S: sw_astring); virtual;
  432. {a}procedure DeleteAllLines; virtual;
  433. {a}procedure DeleteLine(I: sw_integer); virtual;
  434. {a}function InsertLine(LineNo: sw_integer; const S: sw_AString): PCustomLine; virtual;
  435. {a}procedure AddLine(const S: sw_AString); virtual;
  436. {a}procedure GetContent(ALines: PUnsortedStringCollection); virtual;
  437. {a}procedure SetContent(ALines: PUnsortedStringCollection); virtual;
  438. public
  439. procedure Lock(AEditor: PCustomCodeEditor);
  440. procedure UnLock(AEditor: PCustomCodeEditor);
  441. function Locked: boolean;
  442. public
  443. { Syntax highlight }
  444. function UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
  445. function UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer; virtual;
  446. function DoUpdateAttrs(Editor: PCustomCodeEditor; FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
  447. function DoUpdateAttrsRange(Editor: PCustomCodeEditor; FromLine, ToLine: sw_integer;
  448. Attrs: byte): sw_integer; virtual;
  449. public
  450. { Undo info storage }
  451. {a}procedure AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: sw_astring;AFlags : longint); virtual;
  452. {a}procedure AddGroupedAction(AAction : byte); virtual;
  453. {a}procedure CloseGroupedAction(AAction : byte); virtual;
  454. {a}function GetUndoActionCount: sw_integer; virtual;
  455. {a}function GetRedoActionCount: sw_integer; virtual;
  456. procedure UpdateUndoRedo(cm : word; action : byte);virtual;
  457. end;
  458. TCaseAction = (caToLowerCase,caToUpperCase,caToggleCase);
  459. TCustomCodeEditor = object(TScroller)
  460. SelStart : TPoint;
  461. SelEnd : TPoint;
  462. Highlight : TRect;
  463. CurPos : TPoint;
  464. ELockFlag : integer;
  465. NoSelect : Boolean;
  466. AlwaysShowScrollBars: boolean;
  467. public
  468. { constructor Load(var S: TStream);
  469. procedure Store(var S: TStream);}
  470. procedure ConvertEvent(var Event: TEvent); virtual;
  471. procedure HandleEvent(var Event: TEvent); virtual;
  472. procedure SetState(AState: Word; Enable: Boolean); virtual;
  473. procedure LocalMenu(P: TPoint); virtual;
  474. function GetLocalMenu: PMenu; virtual;
  475. function GetCommandTarget: PView; virtual;
  476. function CreateLocalMenuView(var Bounds: TRect; M: PMenu): PMenuPopup; virtual;
  477. function GetPalette: PPalette; virtual;
  478. public
  479. procedure Draw; virtual;
  480. procedure DrawCursor; virtual;
  481. { this is the only way I found to avoid
  482. having the cursor being updated if lock is on PM }
  483. procedure ResetCursor; virtual;
  484. procedure DrawIndicator; virtual;
  485. public
  486. {a}function GetFlags: longint; virtual;
  487. {a}procedure SetFlags(AFlags: longint); virtual;
  488. {a}function GetModified: boolean; virtual;
  489. {a}procedure SetModified(AModified: boolean); virtual;
  490. {a}function GetStoreUndo: boolean; virtual;
  491. {a}procedure SetStoreUndo(AStore: boolean); virtual;
  492. {a}function GetSyntaxCompleted: boolean; virtual;
  493. {a}procedure SetSyntaxCompleted(SC: boolean); virtual;
  494. {a}function GetLastSyntaxedLine: sw_integer; virtual;
  495. {a}procedure SetLastSyntaxedLine(ALine: sw_integer); virtual;
  496. function IsNestedComments(X,Y : sw_integer): boolean; virtual;
  497. function NestedCommentsChangeCheck(CurLine : sw_integer):boolean; virtual;
  498. function IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
  499. function GetReservedColCount: sw_integer; virtual;
  500. {a}function GetTabSize: integer; virtual;
  501. {a}procedure SetTabSize(ATabSize: integer); virtual;
  502. {a}function GetIndentSize: integer; virtual;
  503. {a}procedure SetIndentSize(AIndentSize: integer); virtual;
  504. {a}function IsReadOnly: boolean; virtual;
  505. {a}function IsClipboard: Boolean; virtual;
  506. {a}function GetAutoBrackets: boolean; virtual;
  507. {a}procedure SetAutoBrackets(AutoBrackets: boolean); virtual;
  508. {a}function GetInsertMode: boolean; virtual;
  509. {a}procedure SetInsertMode(InsertMode: boolean); virtual;
  510. procedure SetCurPtr(X,Y: sw_integer); virtual;
  511. function InSelectionArea:boolean; {CurPos in selection area}
  512. procedure GetSelectionArea(var StartP,EndP: TPoint); virtual;
  513. procedure SetSelection(A, B: TPoint); virtual;
  514. procedure SetHighlight(A, B: TPoint); virtual;
  515. procedure ChangeCaseArea(StartP,EndP: TPoint; CaseAction: TCaseAction); virtual;
  516. procedure SetLineFlagState(LineNo: sw_integer; Flags: longint; ASet: boolean);
  517. procedure SetLineFlagExclusive(Flags: longint; LineNo: sw_integer);
  518. procedure Update; virtual;
  519. procedure ScrollTo(X, Y: sw_Integer);
  520. procedure TrackCursor(centre:Tcentre); virtual;
  521. procedure Lock; virtual;
  522. procedure UnLock; virtual;
  523. public
  524. { Text & info storage abstraction }
  525. {a}function GetMaxDisplayLength: sw_integer; virtual; {Max display code points}
  526. {a}function GetLineCount: sw_integer; virtual;
  527. {a}function GetLine(LineNo: sw_integer): PCustomLine; virtual;
  528. {a}function CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer; virtual;
  529. {a}function LinePosToCharIdx(Line,X: sw_integer): sw_integer; virtual;
  530. {a}function GetLineText(I: sw_integer): sw_astring; virtual;
  531. {a}procedure SetDisplayText(I: sw_integer;const S: sw_astring); virtual;
  532. {a}function GetDisplayText(I: sw_integer): sw_astring; virtual;
  533. {a}procedure SetLineText(I: sw_integer;const S: sw_AString); virtual;
  534. {a}procedure GetDisplayTextFormat(I: sw_integer;var DT,DF:sw_astring); virtual;
  535. {a}function GetLineFormat(I: sw_integer): sw_astring; virtual;
  536. {a}procedure SetLineFormat(I: sw_integer;const S: sw_astring); virtual;
  537. {a}procedure DeleteAllLines; virtual;
  538. {a}procedure DeleteLine(I: sw_integer); virtual;
  539. {a}function InsertLine(LineNo: sw_integer; const S: sw_astring): PCustomLine; virtual;
  540. {a}procedure AddLine(const S: sw_astring); virtual;
  541. {a}function GetErrorMessage: string; virtual;
  542. {a}procedure SetErrorMessage(const S: string); virtual;
  543. {a}procedure AdjustSelection(DeltaX, DeltaY: sw_integer);
  544. {a}procedure AdjustSelectionBefore(DeltaX, DeltaY: sw_integer);
  545. {a}procedure AdjustSelectionPos(OldCurPosX, OldCurPosY: sw_integer; DeltaX, DeltaY: sw_integer);
  546. {a}procedure GetContent(ALines: PUnsortedStringCollection); virtual;
  547. {a}procedure SetContent(ALines: PUnsortedStringCollection); virtual;
  548. {a}function LoadFromStream(Stream: PFastBufStream): boolean; virtual;
  549. {a}function SaveToStream(Stream: PStream): boolean; virtual;
  550. {a}function SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;virtual;
  551. function LoadFromFile(const AFileName: string): boolean; virtual;
  552. function SaveToFile(const AFileName: string): boolean; virtual;
  553. function GetBookmark(MarkIdx: sw_integer):TEditorBookMark; virtual;
  554. procedure SetBookmark(MarkIdx: sw_integer; ABookmark: TEditorBookMark); virtual;
  555. function FindMarkLineNr(MarkIdx: sw_integer):sw_integer; virtual;
  556. procedure AdjustBookMark(X, NewX, Y, NewY: sw_integer); virtual;
  557. public
  558. function InsertFrom(Editor: PCustomCodeEditor): Boolean; virtual;
  559. {a}function InsertText(const S: sw_astring): Boolean; virtual;
  560. public
  561. procedure FlagsChanged(OldFlags: longint); virtual;
  562. {a}procedure BindingsChanged; virtual;
  563. procedure ContentsChanged; virtual;
  564. procedure LimitsChanged; virtual;
  565. procedure ModifiedChanged; virtual;
  566. procedure PositionChanged; virtual;
  567. procedure TabSizeChanged; virtual;
  568. procedure SyntaxStateChanged; virtual;
  569. procedure StoreUndoChanged; virtual;
  570. procedure SelectionChanged; virtual;
  571. procedure HighlightChanged; virtual;
  572. {a}procedure DoLimitsChanged; virtual;
  573. public
  574. { Syntax highlight support }
  575. {a}function GetSpecSymbolCount(SpecClass: TSpecSymbolClass): integer; virtual;
  576. {a}function GetSpecSymbol(SpecClass: TSpecSymbolClass; Index: integer): pstring; virtual;
  577. {a}function IsReservedWord(const S: string): boolean; virtual;
  578. {a}function IsAsmReservedWord(const S: string): boolean; virtual;
  579. public
  580. { CodeTemplate support }
  581. {a}function TranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean; virtual;
  582. function SelectCodeTemplate(var ShortCut: string): boolean; virtual;
  583. { CodeComplete support }
  584. {a}function CompleteCodeWord(const WordS: string; var Text: string): boolean; virtual;
  585. {a}function GetCodeCompleteWord: string; virtual;
  586. {a}procedure SetCodeCompleteWord(const S: string); virtual;
  587. {a}function GetCodeCompleteFrag: string; virtual;
  588. {a}procedure SetCodeCompleteFrag(const S: string); virtual;
  589. function GetCompleteState: TCompleteState; virtual;
  590. procedure SetCompleteState(AState: TCompleteState); virtual;
  591. procedure ClearCodeCompleteWord; virtual;
  592. { Fold support }
  593. function GetMaxFoldLevel: sw_integer; virtual;
  594. function GetFoldStringWidth: sw_integer; virtual;
  595. procedure GetFoldStrings(EditorLine: sw_integer; var Prefix, Suffix: openstring); virtual;
  596. {a}function GetFoldCount: sw_integer; virtual;
  597. {a}function GetFold(Index: sw_integer): PFold; virtual;
  598. {a}procedure RegisterFold(AFold: PFold); virtual;
  599. {a}procedure UnRegisterFold(AFold: PFold); virtual;
  600. function ViewToEditorLine(ViewLine: sw_integer): sw_integer;
  601. function EditorToViewLine(EditorLine: sw_integer): sw_integer;
  602. procedure ViewToEditorPoint(P: TPoint; var NP: TPoint);
  603. procedure EditorToViewPoint(P: TPoint; var NP: TPoint);
  604. { Fold support }
  605. function CreateFold(StartY,EndY: sw_integer; Collapsed: boolean): boolean; virtual;
  606. procedure FoldChanged(Fold: PFold); virtual;
  607. procedure RemoveAllFolds; virtual;
  608. public
  609. { Syntax highlight }
  610. {a}function UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
  611. {a}function UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer; virtual;
  612. public
  613. { Undo info storage }
  614. {a}procedure AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: sw_astring;AFlags : longint); virtual;
  615. {a}procedure AddGroupedAction(AAction : byte); virtual;
  616. {a}procedure CloseGroupedAction(AAction : byte); virtual;
  617. {a}function GetUndoActionCount: sw_integer; virtual;
  618. {a}function GetRedoActionCount: sw_integer; virtual;
  619. protected
  620. LastLocalCmd: word;
  621. KeyState : Integer;
  622. Bookmarks : array[0..9] of TEditorBookmark;
  623. DrawCalled,
  624. DrawCursorCalled: boolean;
  625. CurEvent : PEvent;
  626. procedure DrawLines(FirstLine: sw_integer);
  627. function Overwrite: boolean;
  628. function IsModal: boolean;
  629. procedure CheckSels;
  630. procedure CodeCompleteCheck;
  631. procedure CodeCompleteApply;
  632. procedure CodeCompleteCancel;
  633. procedure UpdateUndoRedo(cm : word; action : byte);
  634. procedure HideHighlight;
  635. function ShouldExtend: boolean;
  636. function ValidBlock: boolean;
  637. function GetLineFold(EditorLine: sw_integer): PFold;
  638. function IsLineVisible(EditorLine: sw_integer): boolean; virtual;
  639. function NextVisibleLine(StartLine: sw_integer; Down: boolean): sw_integer;
  640. procedure PushInfo(Const st : string);virtual;
  641. procedure PopInfo;virtual;
  642. public
  643. { Editor primitives }
  644. procedure SelectAll(Enable: boolean); virtual;
  645. procedure CommentSel; virtual;
  646. procedure UnCommentSel; virtual;
  647. public
  648. { Editor commands }
  649. SearchRunCount: integer;
  650. InASCIIMode: boolean;
  651. procedure Indent; virtual;
  652. procedure CharLeft; virtual;
  653. procedure CharRight; virtual;
  654. procedure WordLeft; virtual;
  655. procedure WordRight; virtual;
  656. procedure LineStart; virtual;
  657. procedure LineEnd; virtual;
  658. procedure LineUp; virtual;
  659. procedure LineDown; virtual;
  660. procedure PageUp; virtual;
  661. procedure PageDown; virtual;
  662. procedure ScrollOneUp; virtual;
  663. procedure ScrollOneDown; virtual;
  664. procedure TextStart; virtual;
  665. procedure TextEnd; virtual;
  666. procedure WindowStart; virtual;
  667. procedure WindowEnd; virtual;
  668. procedure JumpSelStart; virtual;
  669. procedure JumpSelEnd; virtual;
  670. procedure JumpMark(MarkIdx: integer); virtual;
  671. procedure DefineMark(MarkIdx: integer); virtual;
  672. procedure JumpToLastCursorPos; virtual;
  673. procedure FindMatchingDelimiter(ScanForward: boolean); virtual;
  674. procedure CreateFoldFromBlock; virtual;
  675. procedure ToggleFold; virtual;
  676. procedure CollapseFold; virtual;
  677. procedure ExpandFold; virtual;
  678. procedure UpperCase; virtual;
  679. procedure LowerCase; virtual;
  680. procedure WordLowerCase; virtual;
  681. procedure WordUpperCase; virtual;
  682. procedure InsertOptions; virtual;
  683. procedure ToggleCase; virtual;
  684. function InsertNewLine: Sw_integer; virtual;
  685. procedure BreakLine; virtual;
  686. procedure BackSpace; virtual;
  687. procedure DelChar; virtual;
  688. procedure DelWord; virtual;
  689. procedure DelToEndOfWord; virtual;
  690. procedure DelStart; virtual;
  691. procedure DelEnd; virtual;
  692. procedure DelLine; virtual;
  693. procedure InsMode; virtual;
  694. procedure StartSelect; virtual;
  695. procedure EndSelect; virtual;
  696. procedure DelSelect; virtual;
  697. procedure HideSelect; virtual;
  698. procedure CopyBlock; virtual;
  699. procedure MoveBlock; virtual;
  700. procedure IndentBlock; virtual;
  701. procedure UnindentBlock; virtual;
  702. procedure SelectWord; virtual;
  703. procedure SelectLine; virtual;
  704. procedure WriteBlock; virtual;
  705. procedure ReadBlock; virtual;
  706. procedure PrintBlock; virtual;
  707. procedure ExpandCodeTemplate; virtual;
  708. procedure AddChar(C: AnsiChar); virtual;
  709. procedure PasteText(P:PAnsiChar; ASize:sw_integer); virtual;
  710. {$ifdef WinClipSupported}
  711. function ClipCopyWin: Boolean; virtual;
  712. function ClipPasteWin: Boolean; virtual;
  713. {$endif WinClipSupported}
  714. function ClipCopy: Boolean; virtual;
  715. procedure ClipCut; virtual;
  716. procedure ClipPaste; virtual;
  717. function GetCurrentWord : string;
  718. function GetCurrentWordArea(var StartP,EndP: TPoint): boolean;
  719. procedure Undo; virtual;
  720. procedure Redo; virtual;
  721. procedure Find; virtual;
  722. procedure Replace; virtual;
  723. procedure DoSearchReplace; virtual;
  724. procedure GotoLine; virtual;
  725. end;
  726. TCodeEditorDialog = function(Dialog: Integer; Info: Pointer): Word;
  727. TEditorInputLine = object(TInputLine)
  728. Procedure HandleEvent(var Event : TEvent);virtual;
  729. end;
  730. PEditorInputLine = ^TEditorInputLine;
  731. TSearchHelperDialog = object(TDialog)
  732. OkButton: PButton;
  733. Procedure HandleEvent(var Event : TEvent);virtual;
  734. end;
  735. PSearchHelperDialog = ^TSearchHelperDialog;
  736. PFPFileInputLine = ^TFPFileInputLine;
  737. TFPFileInputLine = object(TFileInputLine)
  738. constructor Init(var Bounds: TRect; AMaxLen: Sw_Integer);
  739. procedure HandleEvent(var Event: TEvent); virtual;
  740. end;
  741. PFPFileDialog = ^TFPFileDialog;
  742. TFPFileDialog = object(TFileDialog)
  743. constructor Init(AWildCard: TWildStr; const ATitle,
  744. InputName: String; AOptions: Word; HistoryId: Byte);
  745. end;
  746. const
  747. { used for ShiftDel and ShiftIns to avoid
  748. GetShiftState to be considered for extending
  749. selection (PM) }
  750. DontConsiderShiftState: boolean = false;
  751. cut_key:word=kbShiftDel;
  752. copy_key:word=kbCtrlIns;
  753. paste_key:word=kbShiftIns;
  754. all_key:word=kbNoKey;
  755. CodeCompleteMinLen : byte = 4; { minimum length of text to try to complete }
  756. ToClipCmds : TCommandSet = ([cmCut,cmCopy,cmCopyWin,
  757. { cmUnselect should because like cut, copy, copywin:
  758. if there is a selection, it is active, else it isn't }
  759. cmUnselect,cmCommentSel,cmUnCommentSel]);
  760. FromClipCmds : TCommandSet = ([cmPaste]);
  761. NulClipCmds : TCommandSet = ([cmClear]);
  762. UndoCmd : TCommandSet = ([cmUndo]);
  763. RedoCmd : TCommandSet = ([cmRedo]);
  764. function ExtractTabs(S: string; TabSize: Sw_integer): string;
  765. function ExtractTabs(S: AnsiString; TabSize: Sw_integer): AnsiString;
  766. function StdEditorDialog(Dialog: Integer; Info: Pointer): word;
  767. const
  768. DefaultSaveExt : string[12] = '.pas';
  769. FileDir : DirStr = '';
  770. EditorDialog : TCodeEditorDialog = {$ifdef fpc}@{$endif}StdEditorDialog;
  771. Clipboard : PCustomCodeEditor = nil;
  772. FindStr : String[FindStrSize] = '';
  773. ReplaceStr : String[FindStrSize] = '';
  774. FindReplaceEditor : PCustomCodeEditor = nil;
  775. FindFlags : word = ffPromptOnReplace;
  776. {$ifndef NO_UNTYPEDSET}
  777. {$define USE_UNTYPEDSET}
  778. {$endif ndef NO_UNTYPEDSET}
  779. WhiteSpaceChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = [#0,#32,#255];
  780. TabChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = [#9];
  781. HashChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['#'];
  782. AlphaChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['A'..'Z','a'..'z','_'];
  783. NumberChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['0'..'9'];
  784. HexNumberChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['0'..'9','A'..'F','a'..'f'];
  785. RealNumberChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['E','e','.'{,'+','-'}];
  786. procedure RegisterWEditor;
  787. implementation
  788. uses
  789. Strings,Video,MsgBox,App,Validate,
  790. {$ifdef WinClipSupported}
  791. FvClip,
  792. {$endif WinClipSupported}
  793. {$ifdef TEST_REGEXP}
  794. {$ifdef USE_OLD_REGEXP}
  795. oldregexpr,
  796. {$else not USE_OLD_REGEXP}
  797. regexpr,
  798. {$endif not USE_OLD_REGEXP}
  799. {$endif TEST_REGEXP}
  800. WConsts,WCEdit;
  801. type
  802. RecordWord = sw_word;
  803. TFindDialogRec = packed record
  804. Find : String[FindStrSize];
  805. Options : RecordWord{longint};
  806. { checkboxes need 32 bits PM }
  807. { reverted to word in dialogs.TCluster for TP compatibility (PM) }
  808. { anyhow its complete nonsense : you can only have 16 fields
  809. but use a longint to store it !! }
  810. Direction: RecordWord;{ and tcluster has word size }
  811. Scope : RecordWord;
  812. Origin : RecordWord;
  813. end;
  814. TReplaceDialogRec = packed record
  815. Find : String[FindStrSize];
  816. Replace : String[FindStrSize];
  817. Options : RecordWord{longint};
  818. Direction: RecordWord;
  819. Scope : RecordWord;
  820. Origin : RecordWord;
  821. end;
  822. TGotoLineDialogRec = packed record
  823. LineNo : string[5];
  824. Lines : sw_integer;
  825. end;
  826. const
  827. kbShift = kbLeftShift+kbRightShift;
  828. const
  829. FirstKeyCount = 48;
  830. FirstKeys: array[0..FirstKeyCount * 2] of Word = (FirstKeyCount,
  831. Ord(^A), cmWordLeft, Ord(^B), cmJumpLine, Ord(^C), cmPageDown,
  832. Ord(^D), cmCharRight, Ord(^E), cmLineUp,
  833. Ord(^F), cmWordRight, Ord(^G), cmDelChar,
  834. Ord(^H), cmBackSpace, Ord(^J), cmExpandCodeTemplate,
  835. Ord(^K), $FF02, Ord(^L), cmSearchAgain,
  836. Ord(^M), cmNewLine, Ord(^N), cmBreakLine,
  837. Ord(^O), $FF03,
  838. Ord(^P), cmASCIIChar, Ord(^Q), $FF01,
  839. Ord(^R), cmPageUp, Ord(^S), cmCharLeft,
  840. Ord(^T), cmDelToEndOfWord, Ord(^U), cmUndo,
  841. Ord(^V), cmInsMode, Ord(^X), cmLineDown,
  842. Ord(^Y), cmDelLine, Ord(^W), cmScrollOneUp,
  843. Ord(^Z), cmScrollOneDown, kbLeft, cmCharLeft,
  844. kbRight, cmCharRight, kbCtrlLeft, cmWordLeft,
  845. kbCtrlRight, cmWordRight, kbHome, cmLineStart,
  846. kbCtrlHome, cmWindowStart, kbCtrlEnd, cmWindowEnd,
  847. kbEnd, cmLineEnd, kbUp, cmLineUp,
  848. kbDown, cmLineDown, kbPgUp, cmPageUp,
  849. kbPgDn, cmPageDown, kbCtrlPgUp, cmTextStart,
  850. kbCtrlPgDn, cmTextEnd, kbIns, cmInsMode,
  851. kbDel, cmDelChar, kbShiftIns, cmPaste,
  852. kbShiftDel, cmCut, kbCtrlIns, cmCopy,
  853. kbCtrlDel, cmClear,
  854. kbCtrlGrayMul, cmToggleFold, kbCtrlGrayMinus, cmCollapseFold, kbCtrlGrayPlus, cmExpandFold);
  855. QuickKeyCount = 29;
  856. QuickKeys: array[0..QuickKeyCount * 2] of Word = (QuickKeyCount,
  857. Ord('A'), cmReplace, Ord('C'), cmTextEnd,
  858. Ord('D'), cmLineEnd, Ord('F'), cmFind,
  859. Ord('H'), cmDelStart, Ord('R'), cmTextStart,
  860. Ord('S'), cmLineStart, Ord('Y'), cmDelEnd,
  861. Ord('G'), cmJumpLine, Ord('A'), cmReplace,
  862. Ord('B'), cmSelStart, Ord('K'), cmSelEnd,
  863. Ord('P'), cmLastCursorPos,
  864. Ord('E'), cmWindowStart, Ord('T'), cmWindowStart,
  865. Ord('U'), cmWindowEnd, Ord('X'), cmWindowEnd,
  866. Ord('['), cmFindMatchingDelimiter, Ord(']'), cmFindMatchingDelimiterBack,
  867. Ord('0'), cmJumpMark0, Ord('1'), cmJumpMark1, Ord('2'), cmJumpMark2,
  868. Ord('3'), cmJumpMark3, Ord('4'), cmJumpMark4, Ord('5'), cmJumpMark5,
  869. Ord('6'), cmJumpMark6, Ord('7'), cmJumpMark7, Ord('8'), cmJumpMark8,
  870. Ord('9'), cmJumpMark9);
  871. BlockKeyCount = 30;
  872. BlockKeys: array[0..BlockKeyCount * 2] of Word = (BlockKeyCount,
  873. Ord('B'), cmStartSelect, Ord('C'), cmCopyBlock,
  874. Ord('H'), cmHideSelect, Ord('K'), cmEndSelect,
  875. Ord('Y'), cmDelSelect, Ord('V'), cmMoveBlock,
  876. Ord('I'), cmIndentBlock, Ord('U'), cmUnindentBlock,
  877. Ord('T'), cmSelectWord, Ord('L'), cmSelectLine,
  878. Ord('W'), cmWriteBlock, Ord('R'), cmReadBlock,
  879. Ord('P'), cmPrintBlock,
  880. Ord('N'), cmUpperCase, Ord('O'), cmLowerCase,
  881. Ord('D'), cmActivateMenu,
  882. Ord('E'), cmWordLowerCase, Ord('F'), cmWordUpperCase,
  883. Ord('S'), cmSave, Ord('A'), cmCreateFold,
  884. Ord('0'), cmSetMark0, Ord('1'), cmSetMark1, Ord('2'), cmSetMark2,
  885. Ord('3'), cmSetMark3, Ord('4'), cmSetMark4, Ord('5'), cmSetMark5,
  886. Ord('6'), cmSetMark6, Ord('7'), cmSetMark7, Ord('8'), cmSetMark8,
  887. Ord('9'), cmSetMark9);
  888. MiscKeyCount = 6;
  889. MiscKeys: array[0..MiscKeyCount * 2] of Word = (MiscKeyCount,
  890. Ord('A'), cmOpenAtCursor, Ord('B'), cmBrowseAtCursor,
  891. Ord('G'), cmJumpLine, Ord('O'), cmInsertOptions,
  892. Ord('U'), cmToggleCase, Ord('L'), cmSelectLine);
  893. KeyMap: array[0..3] of Pointer = (@FirstKeys, @QuickKeys, @BlockKeys, @MiscKeys);
  894. function ScanKeyMap(KeyMap: Pointer; KeyCode: Word): Word;
  895. type
  896. pword = ^word;
  897. var
  898. p : pword;
  899. count : sw_word;
  900. begin
  901. p:=keymap;
  902. count:=p^;
  903. inc(p);
  904. while (count>0) do
  905. begin
  906. if (lo(p^)=lo(keycode)) and
  907. ((hi(p^)=0) or (hi(p^)=hi(keycode))) then
  908. begin
  909. inc(p);
  910. scankeymap:=p^;
  911. Exit;
  912. end;
  913. inc(p,2);
  914. dec(count);
  915. end;
  916. scankeymap:=0;
  917. end;
  918. function IsWordSeparator(C: AnsiChar): boolean;
  919. begin
  920. IsWordSeparator:=C in
  921. [' ',#0,#255,':','=','''','"',
  922. '.',',','/',';','$','#', { In Lazarus "$", "#" are not word separators }
  923. '(',')','<','>','^','*',
  924. '+','-','?','&','[',']',
  925. '{','}','@','~','%','\',
  926. '!'];
  927. end;
  928. {function IsSpace(C: AnsiChar): boolean;
  929. begin
  930. IsSpace:=C in[' ',#0,#255];
  931. end;}
  932. function LTrim(S: string): string;
  933. begin
  934. while (length(S)>0) and (S[1] in [#0,TAB,#32]) do
  935. Delete(S,1,1);
  936. LTrim:=S;
  937. end;
  938. { TAB are not same as spaces if UseTabs is set PM }
  939. function RTrim(S: string;cut_tabs : boolean): string;
  940. begin
  941. while (length(S)>0) and
  942. ((S[length(S)] in [#0,#32]) or
  943. ((S[Length(S)]=TAB) and cut_tabs)) do
  944. Delete(S,length(S),1);
  945. RTrim:=S;
  946. end;
  947. function Trim(S: string): string;
  948. begin
  949. Trim:=RTrim(LTrim(S),true);
  950. end;
  951. function LTrim(S: AnsiString): AnsiString;
  952. begin
  953. while (length(S)>0) and (S[1] in [#0,TAB,#32]) do
  954. Delete(S,1,1);
  955. LTrim:=S;
  956. end;
  957. { TAB are not same as spaces if UseTabs is set PM }
  958. function RTrim(S: AnsiString;cut_tabs : boolean): AnsiString;
  959. begin
  960. while (length(S)>0) and
  961. ((S[length(S)] in [#0,#32]) or
  962. ((S[Length(S)]=TAB) and cut_tabs)) do
  963. Delete(S,length(S),1);
  964. RTrim:=S;
  965. end;
  966. function Trim(S: AnsiString): AnsiString;
  967. begin
  968. Trim:=RTrim(LTrim(S),true);
  969. end;
  970. function EatIO: integer;
  971. begin
  972. EatIO:=IOResult;
  973. end;
  974. function ExistsFile(const FileName: string): boolean;
  975. var f: file;
  976. Exists: boolean;
  977. begin
  978. if FileName='' then Exists:=false else
  979. begin
  980. {$I-}
  981. Assign(f,FileName);
  982. Reset(f,1);
  983. Exists:=EatIO=0;
  984. Close(f);
  985. EatIO;
  986. {$I+}
  987. end;
  988. ExistsFile:=Exists;
  989. end;
  990. function StrToInt(const S: string): longint;
  991. var L: longint;
  992. C: integer;
  993. begin
  994. Val(S,L,C); if C<>0 then L:=-1;
  995. StrToInt:=L;
  996. end;
  997. type TPosOfs = int64;
  998. function PosToOfs(const X,Y: sw_integer): TPosOfs;
  999. begin
  1000. PosToOfs:=TPosOfs(y) shl (sizeof(sw_integer)*8) or x;
  1001. end;
  1002. function PosToOfsP(const P: TPoint): TPosOfs;
  1003. begin
  1004. PosToOfsP:=PosToOfs(P.X,P.Y);
  1005. end;
  1006. function PointOfs(P: TPoint): TPosOfs;
  1007. begin
  1008. PointOfs:={longint(P.Y)*MaxLineLength+P.X}PosToOfsP(P);
  1009. end;
  1010. function ExtractTabs(S: string; TabSize: Sw_integer): string;
  1011. var
  1012. P,PAdd: Sw_integer;
  1013. begin
  1014. p:=0;
  1015. while p<length(s) do
  1016. begin
  1017. inc(p);
  1018. if s[p]=TAB then
  1019. begin
  1020. PAdd:=TabSize-((p-1) mod TabSize);
  1021. s:=copy(S,1,P-1)+CharStr(' ',PAdd)+copy(S,P+1,Length(s));
  1022. inc(P,PAdd-1);
  1023. end;
  1024. end;
  1025. ExtractTabs:=S;
  1026. end;
  1027. function ExtractTabs(S: AnsiString; TabSize: Sw_integer): AnsiString;
  1028. var
  1029. P,PAdd: Sw_integer;
  1030. begin
  1031. p:=0;
  1032. while p<length(s) do
  1033. begin
  1034. inc(p);
  1035. if s[p]=TAB then
  1036. begin
  1037. PAdd:=TabSize-((p-1) mod TabSize);
  1038. s:=copy(S,1,P-1)+CharStr(' ',PAdd)+copy(S,P+1,Length(s));
  1039. inc(P,PAdd-1);
  1040. end;
  1041. end;
  1042. ExtractTabs:=S;
  1043. end;
  1044. {function CompressUsingTabs(S: string; TabSize: byte): string;
  1045. var TabS: string;
  1046. P: byte;
  1047. begin
  1048. TabS:=CharStr(' ',TabSize);
  1049. repeat
  1050. P:=Pos(TabS,S);
  1051. if P>0 then
  1052. S:=copy(S,1,P-1)+TAB+copy(S,P+TabSize,High(S));
  1053. until P=0;
  1054. CompressUsingTabs:=S;
  1055. end;}
  1056. {*****************************************************************************
  1057. Forward/Backward Scanning
  1058. *****************************************************************************}
  1059. Const
  1060. MaxBufLength = $7fffff00;
  1061. NotFoundValue = -1;
  1062. Type
  1063. Btable = Array[0..255] of Byte;
  1064. Procedure BMFMakeTable(const s:string; Var t : Btable);
  1065. Var
  1066. x : sw_integer;
  1067. begin
  1068. FillChar(t,sizeof(t),length(s));
  1069. For x := length(s) downto 1 do
  1070. if (t[ord(s[x])] = length(s)) then
  1071. t[ord(s[x])] := length(s) - x;
  1072. end;
  1073. function BMFScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
  1074. Var
  1075. buffer : Array[0..MaxBufLength-1] of Byte Absolute block;
  1076. s2 : String;
  1077. len,
  1078. numb : Sw_Word;
  1079. found : Boolean;
  1080. begin
  1081. len:=length(str);
  1082. if len>size then
  1083. begin
  1084. BMFScan := NotFoundValue;
  1085. exit;
  1086. end;
  1087. SetLength(s2,len); { sets the length to that of the search String }
  1088. found:=False;
  1089. numb:=pred(len);
  1090. While (not found) and (numb<size) do
  1091. begin
  1092. { partial match }
  1093. if buffer[numb] = ord(str[len]) then
  1094. begin
  1095. { less partial! }
  1096. if buffer[numb-pred(len)] = ord(str[1]) then
  1097. begin
  1098. move(buffer[numb-pred(len)],s2[1],len);
  1099. if (str=s2) then
  1100. begin
  1101. found:=true;
  1102. break;
  1103. end;
  1104. end;
  1105. inc(numb);
  1106. end
  1107. else
  1108. inc(numb,Bt[buffer[numb]]);
  1109. end;
  1110. if not found then
  1111. BMFScan := NotFoundValue
  1112. else
  1113. BMFScan := numb - pred(len);
  1114. end;
  1115. function BMFIScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
  1116. Var
  1117. buffer : Array[0..MaxBufLength-1] of AnsiChar Absolute block;
  1118. len,
  1119. numb,
  1120. x : Sw_Word;
  1121. found : Boolean;
  1122. p : PAnsiChar;
  1123. c : AnsiChar;
  1124. begin
  1125. len:=length(str);
  1126. if (len=0) or (len>size) then
  1127. begin
  1128. BMFIScan := NotFoundValue;
  1129. exit;
  1130. end;
  1131. found:=False;
  1132. numb:=pred(len);
  1133. While (not found) and (numb<size) do
  1134. begin
  1135. { partial match }
  1136. c:=buffer[numb];
  1137. if c in ['a'..'z'] then
  1138. c:=chr(ord(c)-32);
  1139. if (c=str[len]) then
  1140. begin
  1141. { less partial! }
  1142. p:=@buffer[numb-pred(len)];
  1143. x:=1;
  1144. while (x<=len) do
  1145. begin
  1146. if not(((p^ in ['a'..'z']) and (chr(ord(p^)-32)=str[x])) or
  1147. (p^=str[x])) then
  1148. break;
  1149. inc(p);
  1150. inc(x);
  1151. end;
  1152. if (x>len) then
  1153. begin
  1154. found:=true;
  1155. break;
  1156. end;
  1157. inc(numb);
  1158. end
  1159. else
  1160. inc(numb,Bt[ord(c)]);
  1161. end;
  1162. if not found then
  1163. BMFIScan := NotFoundValue
  1164. else
  1165. BMFIScan := numb - pred(len);
  1166. end;
  1167. Procedure BMBMakeTable(const s:string; Var t : Btable);
  1168. Var
  1169. x : sw_integer;
  1170. begin
  1171. FillChar(t,sizeof(t),length(s));
  1172. For x := 1 to length(s)do
  1173. if (t[ord(s[x])] = length(s)) then
  1174. t[ord(s[x])] := x-1;
  1175. end;
  1176. function BMBScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
  1177. Var
  1178. buffer : Array[0..MaxBufLength-1] of Byte Absolute block;
  1179. s2 : String;
  1180. len : Sw_Word;
  1181. numb : Sw_Integer;
  1182. found : Boolean;
  1183. begin
  1184. len:=length(str);
  1185. if len>size then
  1186. begin
  1187. BMBScan := NotFoundValue;
  1188. exit;
  1189. end;
  1190. SetLength(S2,len); { sets the length to that of the search String }
  1191. found:=False;
  1192. numb:=size-len;
  1193. While (not found) and (numb>=0) do
  1194. begin
  1195. { partial match }
  1196. if buffer[numb] = ord(str[1]) then
  1197. begin
  1198. { less partial! }
  1199. if buffer[numb+pred(len)] = ord(str[len]) then
  1200. begin
  1201. move(buffer[numb],s2[1],len);
  1202. if (str=s2) then
  1203. begin
  1204. found:=true;
  1205. break;
  1206. end;
  1207. end;
  1208. dec(numb);
  1209. end
  1210. else
  1211. dec(numb,Bt[buffer[numb]]);
  1212. end;
  1213. if not found then
  1214. BMBScan := NotFoundValue
  1215. else
  1216. BMBScan := numb;
  1217. end;
  1218. function BMBIScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
  1219. Var
  1220. buffer : Array[0..MaxBufLength-1] of AnsiChar Absolute block;
  1221. len,
  1222. x : Sw_Word;
  1223. numb : Sw_Integer;
  1224. found : Boolean;
  1225. p : PAnsiChar;
  1226. c : AnsiChar;
  1227. begin
  1228. len:=length(str);
  1229. if (len=0) or (len>size) then
  1230. begin
  1231. BMBIScan := NotFoundValue;
  1232. exit;
  1233. end;
  1234. found:=False;
  1235. numb:=size-len;
  1236. While (not found) and (numb>=0) do
  1237. begin
  1238. { partial match }
  1239. c:=buffer[numb];
  1240. if c in ['a'..'z'] then
  1241. c:=chr(ord(c)-32);
  1242. if (c=str[1]) then
  1243. begin
  1244. { less partial! }
  1245. p:=@buffer[numb];
  1246. x:=1;
  1247. while (x<=len) do
  1248. begin
  1249. if not(((p^ in ['a'..'z']) and (chr(ord(p^)-32)=str[x])) or
  1250. (p^=str[x])) then
  1251. break;
  1252. inc(p);
  1253. inc(x);
  1254. end;
  1255. if (x>len) then
  1256. begin
  1257. found:=true;
  1258. break;
  1259. end;
  1260. dec(numb);
  1261. end
  1262. else
  1263. dec(numb,Bt[ord(c)]);
  1264. end;
  1265. if not found then
  1266. BMBIScan := NotFoundValue
  1267. else
  1268. BMBIScan := numb;
  1269. end;
  1270. {*****************************************************************************
  1271. PLine,TLineCollection
  1272. *****************************************************************************}
  1273. constructor TCustomLine.Init(const AText: sw_AString; AFlags: longint);
  1274. begin
  1275. inherited Init;
  1276. SetText(AText);
  1277. end;
  1278. function TCustomLine.GetText: sw_AString;
  1279. begin
  1280. Abstract;GetText:='';
  1281. end;
  1282. procedure TCustomLine.SetText(const AText: sw_AString);
  1283. begin
  1284. Abstract;
  1285. end;
  1286. function TCustomLine.GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo;
  1287. begin
  1288. Abstract;
  1289. GetEditorInfo:=nil;
  1290. end;
  1291. function TCustomLine.GetFlags: longint;
  1292. begin
  1293. Abstract;
  1294. GetFlags:=0;
  1295. end;
  1296. procedure TCustomLine.SetFlags(AFlags: longint);
  1297. begin
  1298. Abstract;
  1299. end;
  1300. function TCustomLine.IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
  1301. begin
  1302. IsFlagSet:=(GetFlags and AFlag)=AFlag;
  1303. end;
  1304. procedure TCustomLine.SetFlagState(AFlag: longint; ASet: boolean);
  1305. var N,O: longint;
  1306. begin
  1307. O:=GetFlags; N:=O;
  1308. if ASet then
  1309. N:=N or AFlag
  1310. else
  1311. N:=N and (not AFlag);
  1312. if N<>O then
  1313. SetFlags(N);
  1314. end;
  1315. procedure TCustomLine.InsertMark(Editor: PCustomCodeEditor; Mark: PEditorBookMark);
  1316. var LI : PEditorLineInfo;
  1317. begin
  1318. LI:=GetEditorInfo(@Editor);
  1319. if Assigned(LI) then LI^.InsertMark(Mark);
  1320. end;
  1321. procedure TCustomLine.DeleteMark(Editor: PCustomCodeEditor; Mark: PEditorBookMark);
  1322. var LI : PEditorLineInfo;
  1323. begin
  1324. LI:=GetEditorInfo(@Editor);
  1325. if Assigned(LI) then LI^.DeleteMark(Mark);
  1326. end;
  1327. function TCustomLine.MarkCount(Editor: PCustomCodeEditor):Sw_integer;
  1328. var LI : PEditorLineInfo;
  1329. begin
  1330. LI:=GetEditorInfo(@Editor);
  1331. if Assigned(LI) then MarkCount:=LI^.MarkCount else MarkCount:=0;
  1332. end;
  1333. function TCustomLine.GetMark(Editor: PCustomCodeEditor; Index: Sw_integer):PEditorBookMark;
  1334. var LI : PEditorLineInfo;
  1335. begin
  1336. LI:=GetEditorInfo(@Editor);
  1337. if Assigned(LI) then GetMark:=LI^.GetMark(Index) else GetMark:=nil;
  1338. end;
  1339. procedure TCustomLine.AdjustMark(Editor: PCustomCodeEditor; APosX,Adjustment: Sw_integer);
  1340. var LI : PEditorLineInfo;
  1341. begin
  1342. LI:=GetEditorInfo(@Editor);
  1343. if Assigned(LI) then LI^.AdjustMark(APosX,Adjustment);
  1344. end;
  1345. procedure TCustomLine.AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor);
  1346. begin
  1347. { Abstract }
  1348. end;
  1349. procedure TCustomLine.RemoveEditorInfo(AEditor: PCustomCodeEditor);
  1350. begin
  1351. { Abstract }
  1352. end;
  1353. destructor TCustomLine.Done;
  1354. begin
  1355. inherited Done;
  1356. end;
  1357. function TLineCollection.At(Index: sw_Integer): PCustomLine;
  1358. begin
  1359. At:=inherited At(Index);
  1360. end;
  1361. function TEditorBookMarkCollection.At(Index: sw_Integer): PEditorBookMark;
  1362. begin
  1363. At:=inherited At(Index);
  1364. end;
  1365. constructor TFold.Init(AEditor: PCustomCodeEditor; AParentFold: PFold; ACollapsed: boolean);
  1366. begin
  1367. inherited Init;
  1368. New(Childs, Init(10,10));
  1369. Editor:=AEditor;
  1370. ParentFold:=AParentFold;
  1371. if Assigned(ParentFold) then
  1372. ParentFold^.AddChildReference(@Self);
  1373. Collapsed_:=ACollapsed;
  1374. if Assigned(AEditor) then
  1375. Editor^.RegisterFold(@Self);
  1376. end;
  1377. procedure TFold.AddReference(P: PObject);
  1378. begin
  1379. Inc(ReferenceCount);
  1380. end;
  1381. procedure TFold.RemoveReference(P: PObject);
  1382. begin
  1383. Dec(ReferenceCount);
  1384. if CanDispose then
  1385. Free;
  1386. end;
  1387. procedure TFold.AddLineReference(Line: PEditorLineInfo);
  1388. begin
  1389. Inc(LineCount_);
  1390. AddReference(Line);
  1391. end;
  1392. procedure TFold.RemoveLineReference(Line: PEditorLineInfo);
  1393. begin
  1394. Dec(LineCount_);
  1395. RemoveReference(Line);
  1396. end;
  1397. procedure TFold.AddChildReference(Fold: PFold);
  1398. begin
  1399. Childs^.Insert(Fold);
  1400. AddReference(Fold);
  1401. end;
  1402. procedure TFold.RemoveChildReference(Fold: PFold);
  1403. begin
  1404. Childs^.Delete(Fold);
  1405. RemoveReference(Fold);
  1406. end;
  1407. function TFold.CanDispose: boolean;
  1408. begin
  1409. CanDispose:=ReferenceCount<=0;
  1410. end;
  1411. function TFold.IsCollapsed: boolean;
  1412. var C: boolean;
  1413. begin
  1414. C:=Collapsed_;
  1415. if Assigned(ParentFold) then C:=C or ParentFold^.IsCollapsed;
  1416. IsCollapsed:=C;
  1417. end;
  1418. function TFold.IsParent(AFold: PFold): boolean;
  1419. var P: boolean;
  1420. begin
  1421. P:=(ParentFold=AFold);
  1422. if Assigned(ParentFold) then P:=P or ParentFold^.IsParent(AFold);
  1423. IsParent:=P;
  1424. end;
  1425. function TFold.GetLineCount: sw_integer;
  1426. var Count: sw_integer;
  1427. procedure AddIt(P: PFold);
  1428. begin
  1429. Inc(Count,P^.GetLineCount);
  1430. end;
  1431. begin
  1432. Count:=LineCount_;
  1433. if assigned(Childs) then Childs^.ForEach(TCallbackProcParam(@AddIt));
  1434. GetLineCount:=Count;
  1435. end;
  1436. procedure TFold.Collapse(ACollapse: boolean);
  1437. begin
  1438. if ACollapse<>Collapsed_ then
  1439. begin
  1440. Collapsed_:=ACollapse;
  1441. if (not Collapsed_) and Assigned(ParentFold) then
  1442. ParentFold^.Collapse(false);
  1443. Changed;
  1444. end;
  1445. end;
  1446. procedure TFold.Changed;
  1447. begin
  1448. if Assigned(Editor) then
  1449. Editor^.FoldChanged(@Self);
  1450. end;
  1451. function TFold.GetLevel: sw_integer;
  1452. var Level: sw_integer;
  1453. begin
  1454. Level:=0;
  1455. if Assigned(ParentFold) then
  1456. Inc(Level,1+ParentFold^.GetLevel);
  1457. GetLevel:=Level;
  1458. end;
  1459. destructor TFold.Done;
  1460. begin
  1461. if Assigned(ParentFold) then
  1462. ParentFold^.RemoveChildReference(@Self);
  1463. if Assigned(Editor) then
  1464. Editor^.UnRegisterFold(@Self);
  1465. Childs^.DeleteAll; Dispose(Childs, Done);
  1466. inherited Done;
  1467. end;
  1468. function TFoldCollection.At(Index: sw_Integer): PFold;
  1469. begin
  1470. At:=inherited At(Index);
  1471. end;
  1472. constructor TEditorLineInfo.Init(AEditor: PCustomCodeEditor);
  1473. begin
  1474. inherited Init;
  1475. Editor:=AEditor;
  1476. end;
  1477. function TEditorLineInfo.GetFormat: sw_astring;
  1478. begin
  1479. {$if sizeof(sw_astring)>8}
  1480. GetFormat:=GetStr(Format);
  1481. {$else}
  1482. GetFormat:=Format;
  1483. {$endif}
  1484. end;
  1485. procedure TEditorLineInfo.SetFormat(const AFormat: sw_astring);
  1486. begin
  1487. {$if sizeof(sw_astring)>8}
  1488. SetStr(Format,AFormat);
  1489. {$else}
  1490. Format:=AFormat;
  1491. {$endif}
  1492. end;
  1493. procedure TEditorLineInfo.SetFold(AFold: PFold);
  1494. begin
  1495. if Assigned(Fold) then
  1496. Fold^.RemoveLineReference(@Self);
  1497. Fold:=AFold;
  1498. if Assigned(Fold) then
  1499. Fold^.AddLineReference(@Self);
  1500. end;
  1501. procedure TEditorLineInfo.InsertMark(Mark:PEditorBookMark);
  1502. begin
  1503. if not assigned(BookMarks) then
  1504. New(BookMarks, Init(2,2));
  1505. BookMarks^.Insert(Mark);
  1506. end;
  1507. procedure TEditorLineInfo.DeleteMark(Mark:PEditorBookMark);
  1508. begin
  1509. if assigned(BookMarks) then BookMarks^.Delete(Mark);
  1510. end;
  1511. function TEditorLineInfo.MarkCount:Sw_integer;
  1512. begin
  1513. if assigned(BookMarks) then
  1514. MarkCount:=BookMarks^.Count
  1515. else MarkCount:=0;
  1516. end;
  1517. function TEditorLineInfo.GetMark(Index:Sw_integer):PEditorBookMark;
  1518. begin
  1519. if assigned(BookMarks) then
  1520. GetMark:=BookMarks^.at(Index)
  1521. else GetMark:=nil;
  1522. end;
  1523. procedure TEditorLineInfo.AdjustMark(APosX,Adjustment:Sw_integer);
  1524. var Index : sw_integer;
  1525. Mark:PEditorBookMark;
  1526. begin
  1527. if not assigned(BookMarks) then exit;
  1528. for Index:=1 to BookMarks^.Count do
  1529. begin
  1530. Mark:=BookMarks^.at(Index-1);
  1531. if Mark^.Pos.X >=APosX then
  1532. Mark^.Pos.X:=Mark^.Pos.X+Adjustment
  1533. else
  1534. if (Adjustment < 0) and (Mark^.Pos.X>(APosX+Adjustment)) then
  1535. Mark^.Pos.X:=APosX+Adjustment;
  1536. end;
  1537. end;
  1538. destructor TEditorLineInfo.Done;
  1539. begin
  1540. {$if sizeof(sw_astring)>8}
  1541. if Format<>nil then
  1542. DisposeStr(Format);
  1543. Format:=nil;
  1544. {$else}
  1545. Format:='';
  1546. {$endif}
  1547. SetFold(nil);
  1548. if assigned(BookMarks) then
  1549. begin
  1550. BookMarks^.DeleteAll;
  1551. Dispose(BookMarks,Done);
  1552. BookMarks:=nil;
  1553. end;
  1554. inherited Done;
  1555. end;
  1556. function TEditorLineInfoCollection.At(Index: sw_Integer): PEditorLineInfo;
  1557. begin
  1558. At:=inherited At(Index);
  1559. end;
  1560. function TEditorBindingCollection.At(Index: sw_Integer): PEditorBinding;
  1561. begin
  1562. At:=inherited At(Index);
  1563. end;
  1564. constructor TEditorBinding.Init(AEditor: PCustomCodeEditor);
  1565. begin
  1566. inherited Init;
  1567. Editor:=AEditor;
  1568. end;
  1569. destructor TEditorBinding.Done;
  1570. begin
  1571. inherited Done;
  1572. end;
  1573. constructor TCustomCodeEditorCore.Init;
  1574. begin
  1575. inherited Init;
  1576. New(Bindings, Init(10,10));
  1577. end;
  1578. procedure TCustomCodeEditorCore.BindEditor(AEditor: PCustomCodeEditor);
  1579. var B: PEditorBinding;
  1580. Count,I,Idx: sw_integer;
  1581. L: PCustomLine;
  1582. begin
  1583. assert(Aeditor<>nil);
  1584. New(B, Init(AEditor));
  1585. Bindings^.Insert(B);
  1586. Idx:=Bindings^.IndexOf(B);
  1587. Count:=GetLineCount;
  1588. for I:=0 to Count-1 do
  1589. begin
  1590. L:=GetLine(I);
  1591. if Assigned(L) then
  1592. L^.AddEditorInfo(Idx,AEditor);
  1593. end;
  1594. BindingsChanged;
  1595. end;
  1596. procedure TCustomCodeEditorCore.UnBindEditor(AEditor: PCustomCodeEditor);
  1597. var B: PEditorBinding;
  1598. Count,I: sw_integer;
  1599. L: PCustomLine;
  1600. begin
  1601. assert(Aeditor<>nil);
  1602. B:=SearchBinding(AEditor);
  1603. if Assigned(B) then
  1604. begin
  1605. Count:=GetLineCount;
  1606. for I:=0 to Count-1 do
  1607. begin
  1608. L:=GetLine(I);
  1609. if Assigned(L) then
  1610. L^.RemoveEditorInfo(AEditor);
  1611. end;
  1612. Bindings^.Free(B);
  1613. BindingsChanged;
  1614. end;
  1615. end;
  1616. function TCustomCodeEditorCore.IsEditorBound(AEditor: PCustomCodeEditor): boolean;
  1617. begin
  1618. IsEditorBound:=SearchBinding(AEditor)<>nil;
  1619. end;
  1620. function TCustomCodeEditorCore.GetBindingCount: sw_integer;
  1621. begin
  1622. GetBindingCount:=Bindings^.Count;
  1623. end;
  1624. function TCustomCodeEditorCore.GetBindingIndex(AEditor: PCustomCodeEditor): sw_integer;
  1625. var B: PEditorBinding;
  1626. begin
  1627. B:=SearchBinding(AEditor);
  1628. GetBindingIndex:=Bindings^.IndexOf(B);
  1629. end;
  1630. function TCustomCodeEditorCore.SearchBinding(AEditor: PCustomCodeEditor): PEditorBinding;
  1631. function SearchEditor(P: PEditorBinding): boolean;
  1632. begin
  1633. SearchEditor:=P^.Editor=AEditor;
  1634. end;
  1635. begin
  1636. SearchBinding:=Bindings^.FirstThat(TCallbackFunBoolParam(@SearchEditor));
  1637. end;
  1638. function TCustomCodeEditorCore.CanDispose: boolean;
  1639. begin
  1640. CanDispose:=Assigned(Bindings) and (Bindings^.Count=0);
  1641. end;
  1642. function TCustomCodeEditorCore.GetModified: boolean;
  1643. begin
  1644. Abstract;
  1645. GetModified:=true;
  1646. end;
  1647. function TCustomCodeEditorCore.GetChangedLine: sw_integer;
  1648. begin
  1649. GetChangedLine:=ChangedLine;
  1650. end;
  1651. procedure TCustomCodeEditorCore.SetModified(AModified: boolean);
  1652. begin
  1653. Abstract;
  1654. end;
  1655. function TCustomCodeEditorCore.GetStoreUndo: boolean;
  1656. begin
  1657. Abstract;
  1658. GetStoreUndo:=false;
  1659. end;
  1660. procedure TCustomCodeEditorCore.SetStoreUndo(AStore: boolean);
  1661. begin
  1662. Abstract;
  1663. end;
  1664. function TCustomCodeEditorCore.GetSyntaxCompleted: boolean;
  1665. begin
  1666. Abstract;
  1667. GetSyntaxCompleted:=true;
  1668. end;
  1669. procedure TCustomCodeEditorCore.SetSyntaxCompleted(SC : boolean);
  1670. begin
  1671. Abstract;
  1672. end;
  1673. function TCustomCodeEditorCore.IsClipboard: Boolean;
  1674. function IsClip(P: PEditorBinding): boolean;
  1675. begin
  1676. IsClip:=(P^.Editor=Clipboard);
  1677. end;
  1678. begin
  1679. IsClipBoard:=Bindings^.FirstThat(TCallbackFunBoolParam(@IsClip))<>nil;
  1680. end;
  1681. function TCustomCodeEditorCore.GetTabSize: integer;
  1682. begin
  1683. Abstract;
  1684. GetTabSize:=0;
  1685. end;
  1686. procedure TCustomCodeEditorCore.SetTabSize(ATabSize: integer);
  1687. begin
  1688. Abstract;
  1689. end;
  1690. function TCustomCodeEditorCore.GetIndentSize: integer;
  1691. begin
  1692. Abstract;
  1693. GetIndentSize:=0;
  1694. end;
  1695. procedure TCustomCodeEditorCore.SetIndentSize(AIndentSize: integer);
  1696. begin
  1697. Abstract;
  1698. end;
  1699. procedure TCustomCodeEditorCore.LimitsChanged;
  1700. begin
  1701. if Locked then
  1702. LimitsChangedCalled:=true
  1703. else
  1704. DoLimitsChanged;
  1705. end;
  1706. procedure TCustomCodeEditorCore.ContentsChanged;
  1707. begin
  1708. if Locked then
  1709. ContentsChangedCalled:=true
  1710. else
  1711. DoContentsChanged;
  1712. end;
  1713. procedure TCustomCodeEditorCore.ModifiedChanged;
  1714. begin
  1715. if Locked then
  1716. ModifiedChangedCalled:=true
  1717. else
  1718. DoModifiedChanged;
  1719. end;
  1720. procedure TCustomCodeEditorCore.TabSizeChanged;
  1721. begin
  1722. if Locked then
  1723. TabSizeChangedCalled:=true
  1724. else
  1725. DoTabSizeChanged;
  1726. end;
  1727. procedure TCustomCodeEditorCore.StoreUndoChanged;
  1728. begin
  1729. if Locked then
  1730. StoreUndoChangedCalled:=true
  1731. else
  1732. DoStoreUndoChanged;
  1733. end;
  1734. procedure TCustomCodeEditorCore.BindingsChanged;
  1735. procedure CallIt(P: PEditorBinding);
  1736. begin
  1737. P^.Editor^.BindingsChanged;
  1738. end;
  1739. begin
  1740. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1741. end;
  1742. procedure TCustomCodeEditorCore.DoLimitsChanged;
  1743. procedure CallIt(P: PEditorBinding);
  1744. begin
  1745. P^.Editor^.DoLimitsChanged;
  1746. end;
  1747. begin
  1748. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1749. end;
  1750. procedure TCustomCodeEditorCore.DoContentsChanged;
  1751. procedure CallIt(P: PEditorBinding);
  1752. begin
  1753. P^.Editor^.ContentsChanged;
  1754. end;
  1755. begin
  1756. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1757. end;
  1758. procedure TCustomCodeEditorCore.DoModifiedChanged;
  1759. procedure CallIt(P: PEditorBinding);
  1760. begin
  1761. P^.Editor^.ModifiedChanged;
  1762. end;
  1763. begin
  1764. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1765. end;
  1766. procedure TCustomCodeEditorCore.DoTabSizeChanged;
  1767. procedure CallIt(P: PEditorBinding);
  1768. begin
  1769. P^.Editor^.TabSizeChanged;
  1770. end;
  1771. begin
  1772. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1773. end;
  1774. procedure TCustomCodeEditorCore.UpdateUndoRedo(cm : word; action : byte);
  1775. procedure CallIt(P: PEditorBinding);
  1776. begin
  1777. if (P^.Editor^.State and sfActive)<>0 then
  1778. begin
  1779. P^.Editor^.UpdateUndoRedo(cm,action);
  1780. if cm=cmUndo then
  1781. begin
  1782. P^.Editor^.SetCmdState(UndoCmd,true);
  1783. P^.Editor^.SetCmdState(RedoCmd,false);
  1784. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  1785. end;
  1786. end;
  1787. end;
  1788. begin
  1789. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1790. end;
  1791. procedure TCustomCodeEditorCore.DoStoreUndoChanged;
  1792. procedure CallIt(P: PEditorBinding);
  1793. begin
  1794. P^.Editor^.StoreUndoChanged;
  1795. end;
  1796. begin
  1797. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1798. end;
  1799. procedure TCustomCodeEditorCore.DoSyntaxStateChanged;
  1800. procedure CallIt(P: PEditorBinding);
  1801. begin
  1802. P^.Editor^.SyntaxStateChanged;
  1803. end;
  1804. begin
  1805. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1806. end;
  1807. function TCustomCodeEditorCore.GetLastVisibleLine : sw_integer;
  1808. var
  1809. y : sw_integer;
  1810. procedure CallIt(P: PEditorBinding);
  1811. begin
  1812. if y < P^.Editor^.Delta.Y+P^.Editor^.Size.Y then
  1813. y:=P^.Editor^.Delta.Y+P^.Editor^.Size.Y;
  1814. end;
  1815. begin
  1816. y:=0;
  1817. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  1818. GetLastVisibleLine:=y;
  1819. end;
  1820. function TCustomCodeEditorCore.SaveToStream(Editor: PCustomCodeEditor; Stream: PStream): boolean;
  1821. var A,B: TPoint;
  1822. begin
  1823. A.Y:=0; A.X:=0;
  1824. B.Y:=GetLineCount-1;
  1825. if GetLineCount>0 then
  1826. B.X:=length(GetDisplayText(B.Y))
  1827. else
  1828. B.X:=0;
  1829. SaveToStream:=SaveAreaToStream(Editor,Stream,A,B);
  1830. end;
  1831. procedure TCustomCodeEditorCore.ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean);
  1832. begin
  1833. Abstract;
  1834. end;
  1835. procedure TCustomCodeEditorCore.IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:sw_astring);
  1836. begin
  1837. Abstract;
  1838. end;
  1839. function TCustomCodeEditorCore.IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): sw_astring;
  1840. begin
  1841. Abstract;
  1842. IGetLineFormat:='';
  1843. end;
  1844. procedure TCustomCodeEditorCore.ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: sw_astring);
  1845. begin
  1846. Abstract;
  1847. end;
  1848. function TCustomCodeEditorCore.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
  1849. var S: sw_astring;
  1850. TabSize,CP,RX,NextInc: sw_integer;
  1851. begin
  1852. S:=GetLineText(Line);
  1853. (* this would fasten the code
  1854. but UseTabCharacters is set for Editor not for EditorCore
  1855. objects,which is dangerous anyway and should be changed ... PM
  1856. if not IsFlagSet(efUseTabCharacters) then
  1857. begin
  1858. if CharIdx<=Length(S) then
  1859. CharIdxToLinePos:=CharIdx-1
  1860. else
  1861. CharIdxToLinePos:=Length(S)-1;
  1862. exit;
  1863. end; *)
  1864. TabSize:=GetTabSize;
  1865. CP:=1; RX:=0;
  1866. NextInc:=0;
  1867. while {(CP<=length(S)) and }(CP<=CharIdx) do
  1868. begin
  1869. if NextInc>0 then
  1870. Inc(RX,NextInc);
  1871. if (CP<=length(S)) and (S[CP]=TAB) then
  1872. NextInc:=TabSize-(RX mod TabSize) -1
  1873. else
  1874. NextInc:=0;
  1875. Inc(RX);
  1876. Inc(CP);
  1877. end;
  1878. CharIdxToLinePos:=RX-1;
  1879. end;
  1880. function TCustomCodeEditorCore.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
  1881. var S: sw_astring;
  1882. TabSize,CP,RX: sw_integer;
  1883. begin
  1884. TabSize:=GetTabSize;
  1885. S:=GetLineText(Line);
  1886. (*
  1887. if not IsFlagSet(efUseTabCharacters) then
  1888. begin
  1889. if S='' then
  1890. CP:=0
  1891. else if (Line<Length(S)) then
  1892. LinePosToCharIdx:=Line+1
  1893. else
  1894. LinePosToCharIdx:=Length(S);
  1895. exit;
  1896. end; *)
  1897. if S='' then
  1898. CP:=X+1
  1899. else
  1900. begin
  1901. CP:=0; RX:=0;
  1902. while (RX<=X) {and (CP<=length(S))} do
  1903. begin
  1904. Inc(CP);
  1905. if (CP<=length(S)) and
  1906. (S[CP]=TAB) then
  1907. Inc(RX,TabSize-(RX mod TabSize))
  1908. else
  1909. Inc(RX);
  1910. end;
  1911. end;
  1912. LinePosToCharIdx:=CP;
  1913. end;
  1914. function TCustomCodeEditorCore.GetLineCount: sw_integer;
  1915. begin
  1916. Abstract;
  1917. GetLineCount:=0;
  1918. end;
  1919. function TCustomCodeEditorCore.GetLine(LineNo: sw_integer): PCustomLine;
  1920. begin
  1921. Abstract;
  1922. GetLine:=nil;
  1923. end;
  1924. function TCustomCodeEditorCore.GetLineText(LineNo: sw_integer): sw_astring;
  1925. begin
  1926. Abstract;
  1927. GetLineText:='';
  1928. end;
  1929. procedure TCustomCodeEditorCore.SetDisplayText(I: sw_integer;const S: sw_astring);
  1930. begin
  1931. Abstract;
  1932. end;
  1933. function TCustomCodeEditorCore.GetDisplayText(I: sw_integer): sw_astring;
  1934. begin
  1935. Abstract;
  1936. GetDisplayText:='';
  1937. end;
  1938. procedure TCustomCodeEditorCore.SetLineText(I: sw_integer;const S: sw_AString);
  1939. begin
  1940. Abstract;
  1941. end;
  1942. procedure TCustomCodeEditorCore.GetDisplayTextFormat(Editor: PCustomCodeEditor; I: sw_integer;var DT,DF:sw_astring);
  1943. begin
  1944. IGetDisplayTextFormat(SearchBinding(Editor),I,DT,DF);
  1945. end;
  1946. function TCustomCodeEditorCore.GetLineFormat(Editor: PCustomCodeEditor; I: sw_integer): sw_astring;
  1947. begin
  1948. GetLineFormat:=IGetLineFormat(SearchBinding(Editor),I);
  1949. end;
  1950. procedure TCustomCodeEditorCore.SetLineFormat(Editor: PCustomCodeEditor; I: sw_integer; const S: sw_astring);
  1951. begin
  1952. ISetLineFormat(SearchBinding(Editor),I,S);
  1953. end;
  1954. procedure TCustomCodeEditorCore.DeleteAllLines;
  1955. begin
  1956. Abstract;
  1957. end;
  1958. procedure TCustomCodeEditorCore.DeleteLine(I: sw_integer);
  1959. begin
  1960. Abstract;
  1961. end;
  1962. function TCustomCodeEditorCore.InsertLine(LineNo: sw_integer; const S: sw_AString): PCustomLine;
  1963. begin
  1964. Abstract;
  1965. InsertLine:=nil; { eliminate compiler warning }
  1966. end;
  1967. procedure TCustomCodeEditorCore.AddLine(const S: sw_AString);
  1968. begin
  1969. Abstract;
  1970. end;
  1971. procedure TCustomCodeEditorCore.GetContent(ALines: PUnsortedStringCollection);
  1972. begin
  1973. Abstract;
  1974. end;
  1975. procedure TCustomCodeEditorCore.SetContent(ALines: PUnsortedStringCollection);
  1976. begin
  1977. Abstract;
  1978. end;
  1979. function TCustomCodeEditorCore.Locked: boolean;
  1980. begin
  1981. Locked:=LockFlag>0;
  1982. end;
  1983. procedure TCustomCodeEditorCore.Lock(AEditor: PCustomCodeEditor);
  1984. begin
  1985. Inc(LockFlag);
  1986. end;
  1987. procedure TCustomCodeEditorCore.UnLock(AEditor: PCustomCodeEditor);
  1988. begin
  1989. {$ifdef DEBUG}
  1990. if LockFlag=0 then
  1991. Bug('negative lockflag',nil)
  1992. else
  1993. {$endif DEBUG}
  1994. Dec(LockFlag);
  1995. if (LockFlag>0) then
  1996. Exit;
  1997. if LimitsChangedCalled then
  1998. begin
  1999. DoLimitsChanged;
  2000. LimitsChangedCalled:=false;
  2001. end;
  2002. if ModifiedChangedCalled then
  2003. begin
  2004. DoModifiedChanged;
  2005. ModifiedChangedCalled:=false;
  2006. end;
  2007. if TabSizeChangedCalled then
  2008. begin
  2009. DoTabSizeChanged;
  2010. TabSizeChangedCalled:=false;
  2011. end;
  2012. if StoreUndoChangedCalled then
  2013. begin
  2014. DoStoreUndoChanged;
  2015. StoreUndoChangedCalled:=false;
  2016. end;
  2017. if ContentsChangedCalled then
  2018. begin
  2019. DoContentsChanged;
  2020. ContentsChangedCalled:=false;
  2021. end;
  2022. end;
  2023. function TCustomCodeEditorCore.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
  2024. var MinLine: sw_integer;
  2025. procedure CallIt(P: PEditorBinding);
  2026. var I: sw_integer;
  2027. AAttrs:byte;
  2028. begin
  2029. AAttrs:=Attrs;
  2030. if P^.Editor^.NestedCommentsChangeCheck(FromLine) then
  2031. AAttrs:=Attrs or attrForceFull;
  2032. I:=DoUpdateAttrs(P^.Editor,FromLine,AAttrs);
  2033. if (I<MinLine) or (MinLine=-1) then MinLine:=I;
  2034. end;
  2035. begin
  2036. MinLine:=-1;
  2037. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  2038. UpdateAttrs:=MinLine;
  2039. end;
  2040. function TCustomCodeEditorCore.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
  2041. var MinLine: sw_integer;
  2042. procedure CallIt(P: PEditorBinding);
  2043. var I: sw_integer;
  2044. AAttrs:byte;
  2045. begin
  2046. AAttrs:=Attrs;
  2047. if P^.Editor^.NestedCommentsChangeCheck(FromLine) then
  2048. AAttrs:=Attrs or attrForceFull;
  2049. I:=DoUpdateAttrsRange(P^.Editor,FromLine,ToLine,AAttrs);
  2050. if (I<MinLine) or (MinLine=-1) then MinLine:=I;
  2051. end;
  2052. begin
  2053. MinLine:=-1;
  2054. Bindings^.ForEach(TCallbackProcParam(@CallIt));
  2055. UpdateAttrsRange:=MinLine;
  2056. end;
  2057. function TCustomCodeEditorCore.DoUpdateAttrs(Editor: PCustomCodeEditor; FromLine: sw_integer; Attrs: byte): sw_integer;
  2058. type
  2059. TCharClass = (ccWhiteSpace,ccTab,ccAlpha,
  2060. ccNumber,ccHexNumber,ccRealNumber,
  2061. ccHash,ccSymbol);
  2062. var
  2063. SymbolIndex: Sw_integer;
  2064. CurLineNr: Sw_integer;
  2065. CurrentCommentType : Byte;
  2066. CurrentCommentDepth : sw_integer;
  2067. NestedComments,LookForNestedComments : boolean;
  2068. CommentStartX,CommentStartY : sw_integer;
  2069. FirstCC,LastCC: TCharClass;
  2070. InAsm,InComment,InSingleLineComment,InDirective,InString,InStringMultiLine: boolean;
  2071. WhiteSpaceLine,OnlyStringSuffix,StringSuffixEnded : boolean;
  2072. X,ClassStart: Sw_integer;
  2073. SymbolConcat: string; {this can be shortstring after all}
  2074. SymbolWord: string; { shortstring }
  2075. MultiLineStringSuffixLen:Sw_Word;
  2076. LineText,Format: sw_astring;
  2077. function MatchSymbol(const What, S: sw_astring): boolean;
  2078. var Match: boolean;
  2079. begin
  2080. Match:=false;
  2081. if length(What)>=length(S) then
  2082. if copy(What,1+length(What)-length(S),length(S))=S then
  2083. Match:=true;
  2084. MatchSymbol:=Match;
  2085. end;
  2086. var MatchedSymbol: boolean;
  2087. MatchingSymbol: sw_astring;
  2088. type TPartialType = (pmNone,pmLeft,pmRight,pmAny);
  2089. function MatchesAnySpecSymbol(SClass: TSpecSymbolClass; PartialMatch: TPartialType): boolean;
  2090. var S: pstring;
  2091. I: Sw_integer;
  2092. Match,Found: boolean;
  2093. begin
  2094. Found:=false;
  2095. if SymbolConcat<>'' then
  2096. for I:=1 to Editor^.GetSpecSymbolCount(SClass) do
  2097. begin
  2098. SymbolIndex:=I;
  2099. S:=Editor^.GetSpecSymbol(SClass,I-1);
  2100. if (length(SymbolConcat)<length(S^)) or
  2101. ((PartialMatch=pmNone) and (length(S^)<>length(SymbolConcat)))
  2102. then
  2103. Match:=false
  2104. else
  2105. begin
  2106. case PartialMatch of
  2107. pmNone : Match:=SymbolConcat=S^;
  2108. pmRight:
  2109. Match:=copy(SymbolConcat,length(SymbolConcat)-length(S^)+1,length(S^))=S^;
  2110. else Match:=MatchSymbol(SymbolConcat,S^);
  2111. end;
  2112. end;
  2113. if Match then
  2114. begin
  2115. MatchingSymbol:=S^; Found:=true; Break;
  2116. end;
  2117. end;
  2118. MatchedSymbol:=MatchedSymbol or Found;
  2119. MatchesAnySpecSymbol:=Found;
  2120. end;
  2121. function MatchesAsmSpecSymbol(Const OrigWhat: string; SClass: TSpecSymbolClass): boolean;
  2122. var What : String;
  2123. S: pstring;
  2124. I: Sw_integer;
  2125. Match,Found: boolean;
  2126. begin
  2127. Found:=false;
  2128. What:=UpcaseStr(OrigWhat);
  2129. if What<>'' then
  2130. for I:=1 to Editor^.GetSpecSymbolCount(SClass) do
  2131. begin
  2132. SymbolIndex:=I;
  2133. S:=Editor^.GetSpecSymbol(SClass,I-1);
  2134. if (length(S^)<>length(What)) then
  2135. Match:=false
  2136. else
  2137. begin
  2138. {if CaseInsensitive then
  2139. S:=UpcaseStr(S); asm symbols need to be uppercased PM }
  2140. {case PartialMatch of
  2141. pmNone : }
  2142. Match:=What=S^;
  2143. { pmRight:
  2144. Match:=copy(What,length(What)-length(S)+1,length(S))=S;
  2145. else Match:=MatchSymbol(What,S);
  2146. end; }
  2147. end;
  2148. if Match then
  2149. begin
  2150. MatchingSymbol:=S^;
  2151. Found:=true;
  2152. Break;
  2153. end;
  2154. end;
  2155. // MatchedSymbol:=MatchedSymbol or Found;
  2156. MatchesAsmSpecSymbol:=Found;
  2157. end;
  2158. function IsCommentPrefix: boolean;
  2159. begin
  2160. IsCommentPrefix:=MatchesAnySpecSymbol(ssCommentPrefix,pmLeft);
  2161. end;
  2162. function IsMatchingCommentPrefix: boolean;
  2163. var tmpIs : boolean;
  2164. begin {looking for nested comments with matching prefix}
  2165. tmpIs:=(MatchesAnySpecSymbol(ssCommentPrefix,pmLeft));
  2166. if tmpIs
  2167. and (CurrentCommentType=2) {bad, we are making assumption that this is comment opener (* }
  2168. and (LineText[X+1]=')') { looking into next char is bad approach but it is working }
  2169. then
  2170. tmpIs:=false; { in comment this "(*)" is not start of new nested comment but end }
  2171. IsMatchingCommentPrefix:= tmpIs and (CurrentCommentType=SymbolIndex);
  2172. end;
  2173. {** **}
  2174. function IsSingleLineCommentPrefix: boolean;
  2175. begin
  2176. IsSingleLineCommentPrefix:=MatchesAnySpecSymbol(ssCommentSingleLinePrefix,pmLeft);
  2177. end;
  2178. function IsCommentSuffix: boolean;
  2179. var tmpIs : boolean;
  2180. begin
  2181. tmpIs:=(MatchesAnySpecSymbol(ssCommentSuffix,pmRight))
  2182. and (CurrentCommentType=SymbolIndex);
  2183. if tmpIs then
  2184. tmpIs:=(CurLineNr<>CommentStartY) or ((CurLineNr=CommentStartY) and ((X-length(MatchingSymbol))-CommentStartX>=0));
  2185. IsCommentSuffix:=tmpIs;
  2186. end;
  2187. function IsStringPrefix: boolean;
  2188. begin
  2189. IsStringPrefix:=MatchesAnySpecSymbol(ssStringPrefix,pmLeft);
  2190. end;
  2191. function IsStringSuffix: boolean;
  2192. begin
  2193. IsStringSuffix:=MatchesAnySpecSymbol(ssStringSuffix,pmRight);
  2194. end;
  2195. function IsStringMultiLinePrefix: boolean;
  2196. begin
  2197. IsStringMultiLinePrefix:=MatchesAnySpecSymbol(ssStringMultiLinePrefix,pmLeft);
  2198. end;
  2199. function IsStringMultiLineSuffix: boolean;
  2200. begin
  2201. IsStringMultiLineSuffix:=MatchesAnySpecSymbol(ssStringMultiLineSuffix,pmRight);
  2202. end;
  2203. function IsDirectivePrefix: boolean;
  2204. begin
  2205. IsDirectivePrefix:=MatchesAnySpecSymbol(ssDirectivePrefix,pmLeft)
  2206. and (CurrentCommentType=SymbolIndex); {yes - matching comment type}
  2207. end;
  2208. { Directive is treated as comment. Comment suffix will close directive.
  2209. function IsDirectiveSuffix: boolean;
  2210. begin
  2211. IsDirectiveSuffix:=MatchesAnySpecSymbol(ssDirectiveSuffix,pmRight);
  2212. end;}
  2213. function IsAsmPrefix(const WordS: string): boolean;
  2214. { var
  2215. StoredMatchedSymbol : boolean;}
  2216. begin
  2217. {StoredMatchedSymbol:=MatchedSymbol;}
  2218. IsAsmPrefix:=MatchesAsmSpecSymbol(WordS,ssAsmPrefix);
  2219. {MatchedSymbol:=StoredMatchedSymbol;}
  2220. end;
  2221. function IsAsmSuffix(const WordS: string): boolean;
  2222. {var
  2223. StoredMatchedSymbol : boolean;}
  2224. begin
  2225. {StoredMatchedSymbol:=MatchedSymbol;}
  2226. IsAsmSuffix:=MatchesAsmSpecSymbol(WordS,ssAsmSuffix);
  2227. {MatchedSymbol:=StoredMatchedSymbol;}
  2228. end;
  2229. function GetMultiLineStringSuffixLen:Sw_Word;
  2230. var k,i: longword;
  2231. begin
  2232. {get rid of white space at the end of string}
  2233. i:=0;
  2234. for k:=Length(SymbolWord) downto 1 do
  2235. begin
  2236. if not (SymbolWord[k] in [' ',#9,#0,#255]) then
  2237. break;
  2238. inc(i);
  2239. end;
  2240. if i>0 then
  2241. SetLength(SymbolWord,Length(SymbolWord)-i);
  2242. {length of "'" symbols}
  2243. I:=0;
  2244. for k:=Length(SymbolWord) downto 1 do
  2245. begin
  2246. if SymbolWord[k]<>'''' then
  2247. break;
  2248. inc(I);
  2249. end;
  2250. GetMultiLineStringSuffixLen:=I;
  2251. end;
  2252. function GetCharClass(C: AnsiChar): TCharClass;
  2253. var CC: TCharClass;
  2254. begin
  2255. (*
  2256. WhiteSpaceChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = [#0,#32,#255];
  2257. TabChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = [#9];
  2258. HashChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['#'];
  2259. AlphaChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['A'..'Z','a'..'z','_'];
  2260. NumberChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['0'..'9'];
  2261. HexNumberChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['0'..'9','A'..'F','a'..'f'];
  2262. RealNumberChars {$ifdef USE_UNTYPEDSET}: set of AnsiChar {$endif} = ['E','e','.'{,'+','-'}];
  2263. *)
  2264. if C in {$ifdef USE_UNTYPEDSET}[#0,#32,#255]{$else}WhiteSpaceChars{$endif} then
  2265. CC:=ccWhiteSpace
  2266. else if C in {$ifdef USE_UNTYPEDSET}[#9]{$else}TabChars{$endif} then
  2267. CC:=ccTab
  2268. else if C in {$ifdef USE_UNTYPEDSET}['#']{$else}HashChars{$endif} then
  2269. CC:=ccHash
  2270. else if (LastCC=ccHexNumber) and (C in {$ifdef USE_UNTYPEDSET}['0'..'9','A'..'F','a'..'f']{$else}HexNumberChars{$endif}) then
  2271. CC:=ccHexNumber
  2272. else if C in {$ifdef USE_UNTYPEDSET}['0'..'9']{$else}NumberChars{$endif} then
  2273. CC:=ccNumber
  2274. else if (LastCC=ccNumber) and (C in {$ifdef USE_UNTYPEDSET}['E','e','.']{$else}RealNumberChars{$endif}) then
  2275. begin
  2276. if (C='.') then
  2277. begin
  2278. if (X>=length(LineText)) or
  2279. (LineText[X+1]='.') then
  2280. cc:=ccSymbol
  2281. else
  2282. cc:=ccRealNumber;
  2283. end
  2284. else {'E','e'}
  2285. begin
  2286. if (X>=length(LineText)) or
  2287. (LineText[X+1]in ['+','-','0'..'9']) then
  2288. cc:=ccRealNumber
  2289. else
  2290. cc:=ccAlpha
  2291. end;
  2292. end
  2293. else if C in {$ifdef USE_UNTYPEDSET}['A'..'Z','a'..'z','_']{$else}AlphaChars{$endif} then CC:=ccAlpha else
  2294. CC:=ccSymbol;
  2295. GetCharClass:=CC;
  2296. end;
  2297. procedure FormatWord(SClass: TCharClass; StartX:Sw_integer;EndX: Sw_integer);
  2298. var
  2299. C: byte;
  2300. WordS: string; {Note: leave for now as ShortString}
  2301. begin
  2302. C:=0;
  2303. WordS:=copy(LineText,StartX,EndX-StartX+1);
  2304. if (InAsm=true) and (InComment=false) and (InString=false) and
  2305. (InDirective=false) and (SClass=ccAlpha) and IsAsmSuffix(WordS) then InAsm:=false;
  2306. if InDirective then C:=coDirectiveColor else
  2307. if InComment then C:=coCommentColor else
  2308. if InString then C:=coStringColor else
  2309. if InAsm then
  2310. begin
  2311. if (SClass=ccAlpha) and Editor^.IsAsmReservedWord(WordS) then
  2312. C:=coReservedWordColor
  2313. else
  2314. C:=coAssemblerColor;
  2315. end
  2316. else
  2317. case SClass of
  2318. ccWhiteSpace :
  2319. C:=coWhiteSpaceColor;
  2320. ccTab :
  2321. C:=coTabColor;
  2322. ccHexNumber:
  2323. C:=coHexNumberColor;
  2324. ccNumber,
  2325. ccRealNumber :
  2326. C:=coNumberColor;
  2327. ccHash :
  2328. C:=coStringColor;
  2329. ccSymbol :
  2330. C:=coSymbolColor;
  2331. ccAlpha :
  2332. begin
  2333. if Editor^.IsReservedWord(WordS) then
  2334. C:=coReservedWordColor
  2335. else
  2336. C:=coIdentifierColor;
  2337. end;
  2338. end;
  2339. if EndX+1>=StartX then
  2340. FillChar(Format[StartX],EndX+1-StartX,C);
  2341. if (InString=false) and (InAsm=false) and (InComment=false) and
  2342. (InDirective=false) and (SClass=ccAlpha) and IsAsmPrefix(WordS) then
  2343. InAsm:=true;
  2344. end;
  2345. procedure ProcessChar(C: AnsiChar);
  2346. var CC: TCharClass;
  2347. EX: Sw_integer;
  2348. EndComment: pstring;
  2349. begin
  2350. CC:=GetCharClass(C);
  2351. if ClassStart=X then
  2352. FirstCC:=CC;
  2353. if ( (CC<>LastCC) and
  2354. (
  2355. ((FirstCC=ccNumber) and (CC<>ccRealNumber) {and (CC<>ccNumber)}) or
  2356. (((CC<>ccAlpha) or (LastCC<>ccNumber) ) and
  2357. ( (CC<>ccNumber) or (LastCC<>ccAlpha) ) and
  2358. ( (CC<>ccNumber) or (LastCC<>ccHash) ) and
  2359. ( (CC<>ccRealNumber) or (LastCC<>ccNumber))
  2360. ))) or
  2361. (X>length(LineText)) or (CC=ccSymbol) then
  2362. begin
  2363. MatchedSymbol:=false;
  2364. EX:=X-1;
  2365. if length(SymbolWord)>=High(SymbolWord) then
  2366. Delete(SymbolWord,1,1);
  2367. SymbolWord:=SymbolWord+C; { for variable length multi line string end detection }
  2368. if OnlyStringSuffix then
  2369. begin
  2370. OnlyStringSuffix:=(C='''');
  2371. if not OnlyStringSuffix then
  2372. begin
  2373. SetLength(SymbolWord,Length(SymbolWord)-1);
  2374. if (GetMultiLineStringSuffixLen>=MultiLineStringSuffixLen) then
  2375. StringSuffixEnded:=true;
  2376. end;
  2377. end;
  2378. if (CC=ccSymbol) then
  2379. begin
  2380. if length(SymbolConcat)>=High(SymbolConcat) then
  2381. Delete(SymbolConcat,1,1);
  2382. SymbolConcat:=SymbolConcat+C;
  2383. if InComment and IsCommentSuffix then
  2384. Inc(EX) else
  2385. if InString and IsStringSuffix then
  2386. Inc(EX) else
  2387. if InString and (InStringMultiLine=true) and IsStringMultiLineSuffix then
  2388. Inc(EX) {else
  2389. if InDirective and IsDirectiveSuffix then
  2390. Inc(EX)};
  2391. end;
  2392. if StringSuffixEnded then
  2393. begin
  2394. MultiLineStringSuffixLen:=0;
  2395. StringSuffixEnded:=false;
  2396. if (GetMultiLineStringSuffixLen and 1)= 1 then
  2397. InString:=false;
  2398. InStringMultiLine:=false;
  2399. end;
  2400. if (CC<>ccSymbol) then
  2401. begin
  2402. if (CC<>ccWhiteSpace) and (CC<>ccTab) then
  2403. SymbolWord:='';
  2404. OnlyStringSuffix:=false;
  2405. end;
  2406. if CC=ccRealNumber then
  2407. Inc(EX);
  2408. if (C='$') and (MatchedSymbol=false) and (IsDirectivePrefix=false) then
  2409. CC:=ccHexNumber;
  2410. if CC<>ccSymbol then SymbolConcat:='';
  2411. FormatWord(LastCC,ClassStart,EX);
  2412. ClassStart:=EX+1;
  2413. if ClassStart=X then
  2414. FirstCC:=CC;
  2415. case CC of
  2416. ccAlpha : ;
  2417. ccNumber :
  2418. if (LastCC<>ccAlpha) then;
  2419. ccSymbol :
  2420. if (InComment=true) and (CurrentCommentDepth=1) and
  2421. (InDirective=false) and IsDirectivePrefix then
  2422. begin
  2423. InDirective:=true;
  2424. {InComment:=false;} { treat compiler directive as comment }
  2425. {CurrentCommentType:=0;}
  2426. Dec(ClassStart,length(MatchingSymbol)-1);
  2427. end
  2428. else {if (InComment=false) and
  2429. (InDirective=true) and IsDirectiveSuffix then
  2430. InDirective:=false
  2431. else }if (InComment=false) and
  2432. (InString=false) and (InDirective=false) and IsCommentPrefix then
  2433. begin
  2434. InComment:=true;
  2435. LookForNestedComments:=true;
  2436. CurrentCommentType:=SymbolIndex;
  2437. CurrentCommentDepth:=1;
  2438. InSingleLineComment:=IsSingleLineCommentPrefix;
  2439. CommentStartX:=X;
  2440. CommentStartY:=CurLineNr;
  2441. {InString:=false; }
  2442. Dec(ClassStart,length(MatchingSymbol)-1);
  2443. { Remove (* from SymbolConcat to avoid problem with (*) PM }
  2444. { fixes part of bug 1617 }
  2445. { but removed proper directive prefix detection ... }
  2446. { Well. Added false positive end suffix detection. Do not remove. M
  2447. EndComment:=Editor^.GetSpecSymbol(ssCommentSuffix,SymbolIndex);
  2448. if MatchingSymbol[length(MatchingSymbol)]=EndComment^[1] then
  2449. Delete(SymbolConcat,1,length(MatchingSymbol));}
  2450. end
  2451. else if InComment and IsMatchingCommentPrefix then
  2452. begin
  2453. inc(CurrentCommentDepth);
  2454. if LookForNestedComments then
  2455. begin { once per every nested comment test IsNestedComments }
  2456. LookForNestedComments:=false;
  2457. NestedComments:=Editor^.IsNestedComments(X,CurLineNr);
  2458. end;
  2459. end
  2460. else if InComment and IsCommentSuffix then
  2461. begin
  2462. dec(CurrentCommentDepth);
  2463. if not NestedComments then
  2464. CurrentCommentDepth:=0;
  2465. if CurrentCommentDepth=0 then
  2466. begin
  2467. InComment:=false;
  2468. CurrentCommentType:=0;
  2469. InDirective:=false; {not in comment then not in Directive}
  2470. InString:=false;
  2471. InStringMultiLine:=false;
  2472. end;
  2473. end
  2474. else if (InComment=false) and (InString=false) and IsStringPrefix then
  2475. begin
  2476. InString:=true;
  2477. Dec(ClassStart,length(MatchingSymbol)-1);
  2478. end
  2479. else if (InComment=false) and (InString=false) and IsStringMultiLinePrefix then
  2480. begin
  2481. InString:=true;
  2482. InStringMultiLine:=true;
  2483. Dec(ClassStart,length(MatchingSymbol)-1);
  2484. end
  2485. else if (InComment=false) and (InString=true) and (InStringMultiLine=false) and IsStringSuffix then
  2486. begin
  2487. InString:=false;
  2488. end
  2489. else if (InComment=false) and (InString=true) and (InStringMultiLine=true) then
  2490. begin
  2491. if MultiLineStringSuffixLen>2 then
  2492. begin
  2493. if WhiteSpaceLine and IsStringSuffix then
  2494. OnlyStringSuffix:=true;
  2495. end else
  2496. if IsStringMultiLineSuffix then
  2497. begin
  2498. InString:=false;
  2499. InStringMultiLine:=false;
  2500. end;
  2501. end
  2502. else if (InAsm) and (C='@') then
  2503. CC:=ccAlpha; { local labels in asm block will be normal words }
  2504. end;
  2505. if MatchedSymbol and (InComment=false) then
  2506. SymbolConcat:='';
  2507. LastCC:=CC;
  2508. WhiteSpaceLine:=WhiteSpaceLine and ((CC=ccWhiteSpace) or (CC=ccTab));
  2509. end;
  2510. end;
  2511. var Line,NextLine,PrevLine{,OldLine}: PCustomLine;
  2512. PrevLI,LI,nextLI: PEditorLineInfo;
  2513. begin
  2514. if (not Editor^.IsFlagSet(efSyntaxHighlight)) or (FromLine>=GetLineCount) then
  2515. begin
  2516. SetLineFormat(Editor,FromLine,'');
  2517. DoUpdateAttrs:=GetLineCount;
  2518. {$ifdef TEST_PARTIAL_SYNTAX}
  2519. LastSyntaxedLine:=GetLineCount;
  2520. if not SyntaxComplete then
  2521. begin
  2522. SyntaxComplete:=true;
  2523. DoSyntaxStateChanged;
  2524. end;
  2525. (* { no Idle necessary }
  2526. EventMask:=EventMask and not evIdle;*)
  2527. {$endif TEST_PARTIAL_SYNTAX}
  2528. Editor^.SyntaxStateChanged;
  2529. Exit;
  2530. end;
  2531. {$ifdef TEST_PARTIAL_SYNTAX}
  2532. If Editor^.IsFlagSet(efSyntaxHighlight) and (LastSyntaxedLine<FromLine)
  2533. and (FromLine<GetLineCount) then
  2534. CurLineNr:=LastSyntaxedLine
  2535. else
  2536. {$endif TEST_PARTIAL_SYNTAX}
  2537. CurLineNr:=FromLine;
  2538. if CurLineNr>0 then
  2539. PrevLine:=GetLine(CurLineNr-1)
  2540. else
  2541. PrevLine:=nil;
  2542. CommentStartY:=CurLineNr-1; { use in detection for false positive comment: (*) }
  2543. repeat
  2544. Line:=GetLine(CurLineNr);
  2545. if Assigned(PrevLine) then PrevLI:=PrevLine^.GetEditorInfo(Editor) else PrevLI:=nil;
  2546. if Assigned(Line) then LI:=Line^.GetEditorInfo(Editor) else LI:=nil;
  2547. InSingleLineComment:=false;
  2548. if PrevLI<>nil then
  2549. begin
  2550. InString:=PrevLI^.EndsWithString;
  2551. MultiLineStringSuffixLen:=PrevLI^.EndsWithMultiLineStringSuffixLen;
  2552. InAsm:=PrevLI^.EndsWithAsm;
  2553. InComment:=PrevLI^.EndsWithComment and not PrevLI^.EndsInSingleLineComment;
  2554. CurrentCommentType:=PrevLI^.EndCommentType;
  2555. CurrentCommentDepth:=PrevLI^.EndCommentDepth;
  2556. NestedComments:=(PrevLI^.EndNestedComments and 1)=1;
  2557. LookForNestedComments:=(PrevLI^.EndNestedComments and 2)=2;
  2558. InDirective:=PrevLI^.EndsWithDirective;
  2559. end
  2560. else
  2561. begin
  2562. InString:=false;
  2563. MultiLineStringSuffixLen:=0;
  2564. InAsm:=false;
  2565. InComment:=false;
  2566. CurrentCommentType:=0;
  2567. CurrentCommentDepth:=0;
  2568. InDirective:=false;
  2569. NestedComments:=false;
  2570. LookForNestedComments:=false;
  2571. end;
  2572. { OldLine:=Line;}
  2573. if (not Editor^.IsFlagSet(efKeepLineAttr)) then
  2574. begin
  2575. LI^.BeginsWithString:=InString;
  2576. LI^.BeginsWithMultiLineStringSuffixLen:=MultiLineStringSuffixLen;
  2577. LI^.BeginsWithAsm:=InAsm;
  2578. LI^.BeginsWithComment:=InComment;
  2579. LI^.BeginsWithDirective:=InDirective;
  2580. LI^.BeginCommentType:=CurrentCommentType;
  2581. LI^.BeginCommentDepth:=CurrentCommentDepth;
  2582. LI^.BeginNestedComments:=byte(NestedComments) and 1;
  2583. LI^.BeginNestedComments:=LI^.BeginNestedComments or ((byte(LookForNestedComments)and 1) shl 1);
  2584. end
  2585. else
  2586. begin
  2587. InString:=LI^.BeginsWithString;
  2588. MultiLineStringSuffixLen:=LI^.BeginsWithMultiLineStringSuffixLen;
  2589. InAsm:=LI^.BeginsWithAsm;
  2590. InComment:=LI^.BeginsWithComment;
  2591. InDirective:=LI^.BeginsWithDirective;
  2592. CurrentCommentType:=LI^.BeginCommentType;
  2593. CurrentCommentDepth:=LI^.BeginCommentDepth;
  2594. NestedComments:=(LI^.BeginNestedComments and 1)=1;
  2595. LookForNestedComments:=(LI^.BeginNestedComments and 2)=2;
  2596. end;
  2597. LineText:=GetLineText(CurLineNr);
  2598. Format:=CharStr(chr(coTextColor),length(LineText));
  2599. LastCC:=ccWhiteSpace;
  2600. ClassStart:=1;
  2601. SymbolConcat:='';
  2602. SymbolWord:='';
  2603. OnlyStringSuffix:=false;
  2604. StringSuffixEnded:=false;
  2605. InStringMultiLine:=InString;
  2606. WhiteSpaceLine:=true;
  2607. if LineText<>'' then
  2608. begin
  2609. for X:=1 to length(LineText) do
  2610. ProcessChar(LineText[X]);
  2611. Inc(X);
  2612. ProcessChar(' ');
  2613. if (not InString) and (MultiLineStringSuffixLen>0) then
  2614. MultiLineStringSuffixLen:=0;
  2615. if InString and not InStringMultiLine then
  2616. begin
  2617. MultiLineStringSuffixLen:=GetMultiLineStringSuffixLen;
  2618. if MultiLineStringSuffixLen>2 then
  2619. InStringMultiLine:=true;
  2620. end;
  2621. end;
  2622. SetLineFormat(Editor,CurLineNr,Format);
  2623. LI^.EndsWithMultiLineStringSuffixLen:=MultiLineStringSuffixLen;
  2624. LI^.EndsWithString:=InStringMultiLine;
  2625. LI^.EndsWithAsm:=InAsm;
  2626. LI^.EndsWithComment:=InComment;
  2627. LI^.EndsInSingleLineComment:=InSingleLineComment;
  2628. LI^.EndNestedComments:=byte(NestedComments) and 1;
  2629. LI^.EndNestedComments:=LI^.EndNestedComments or ((byte(LookForNestedComments)and 1) shl 1);
  2630. LI^.EndCommentDepth:=CurrentCommentDepth;
  2631. LI^.EndCommentType:=CurrentCommentType;
  2632. LI^.EndsWithDirective:=InDirective;
  2633. Inc(CurLineNr);
  2634. if CurLineNr>=GetLineCount then
  2635. Break;
  2636. NextLine:=GetLine(CurLineNr);
  2637. if Assigned(NextLine) then NextLI:=NextLine^.GetEditorInfo(Editor) else NextLI:=nil;
  2638. if ((Attrs and attrForceFull)=0) then
  2639. if (* Why should we go
  2640. (InAsm=false) and (NextLI^.BeginsWithAsm=false) and
  2641. (InComment=false) and (NextLI^.BeginsWithComment=false) and
  2642. (InDirective=false) and (NextLI^.BeginsWithDirective=false) and
  2643. { OldLine = Line so this is nonsense}
  2644. (PrevLI^.EndsWithComment=LI^.EndsWithComment) and
  2645. (PrevLI^.EndsWithAsm=LI^.EndsWithAsm) and
  2646. (PrevLI^.EndsWithDirective=LI^.EndsWithDirective) and *)
  2647. {$ifdef TEST_PARTIAL_SYNTAX}
  2648. (CurLineNr>FromLine) and
  2649. {$endif TEST_PARTIAL_SYNTAX}
  2650. (NextLI^.BeginsWithString=LI^.EndsWithString) and
  2651. (NextLI^.BeginsWithMultiLineStringSuffixLen=LI^.EndsWithMultiLineStringSuffixLen) and
  2652. (NextLI^.BeginsWithAsm=LI^.EndsWithAsm) and
  2653. (NextLI^.BeginsWithComment=LI^.EndsWithComment) and
  2654. (NextLI^.BeginsWithDirective=LI^.EndsWithDirective) and
  2655. (NextLI^.BeginCommentType=LI^.EndCommentType) and
  2656. (NextLI^.BeginNestedComments=LI^.EndNestedComments) and
  2657. (NextLI^.BeginCommentDepth=LI^.EndCommentDepth) and
  2658. (Length(NextLI^.GetFormat)>0) then
  2659. Break;
  2660. {$ifdef TEST_PARTIAL_SYNTAX}
  2661. if (CurLineNr<GetLineCount) and
  2662. (CurLineNr>FromLine) and
  2663. ((Attrs and attrForceFull)=0) and
  2664. (CurLineNr>GetLastVisibleLine) then
  2665. begin
  2666. If SyntaxComplete then
  2667. begin
  2668. SyntaxComplete:=false;
  2669. DoSyntaxStateChanged;
  2670. end;
  2671. LastSyntaxedLine:=CurLineNr-1;
  2672. break;
  2673. end;
  2674. {$endif TEST_PARTIAL_SYNTAX}
  2675. PrevLine:=Line;
  2676. until false;
  2677. DoUpdateAttrs:=CurLineNr;
  2678. {$ifdef TEST_PARTIAL_SYNTAX}
  2679. If LastSyntaxedLine<CurLineNr-1 then
  2680. LastSyntaxedLine:=CurLineNr-1;
  2681. if CurLineNr=GetLineCount then
  2682. begin
  2683. SyntaxComplete:=true;
  2684. DoSyntaxStateChanged;
  2685. end;
  2686. {$endif TEST_PARTIAL_SYNTAX}
  2687. end;
  2688. function TCustomCodeEditorCore.DoUpdateAttrsRange(Editor: PCustomCodeEditor; FromLine, ToLine: sw_integer;
  2689. Attrs: byte): sw_integer;
  2690. var Line: Sw_integer;
  2691. begin
  2692. Lock(Editor);
  2693. Line:=FromLine;
  2694. repeat
  2695. Line:=DoUpdateAttrs(Editor,Line,Attrs);
  2696. until (Line>=GetLineCount) or (Line>ToLine);
  2697. DoUpdateAttrsRange:=Line;
  2698. Unlock(Editor);
  2699. end;
  2700. procedure TCustomCodeEditorCore.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: sw_astring;AFlags : longint);
  2701. begin
  2702. Abstract;
  2703. end;
  2704. procedure TCustomCodeEditorCore.AddGroupedAction(AAction : byte);
  2705. begin
  2706. Abstract;
  2707. end;
  2708. procedure TCustomCodeEditorCore.CloseGroupedAction(AAction : byte);
  2709. begin
  2710. Abstract;
  2711. end;
  2712. function TCustomCodeEditorCore.GetUndoActionCount: sw_integer;
  2713. begin
  2714. Abstract;
  2715. GetUndoActionCount:=0;
  2716. end;
  2717. function TCustomCodeEditorCore.GetRedoActionCount: sw_integer;
  2718. begin
  2719. Abstract;
  2720. GetRedoActionCount:=0;
  2721. end;
  2722. destructor TCustomCodeEditorCore.Done;
  2723. begin
  2724. {$ifdef DEBUG}
  2725. if Bindings^.Count>0 then
  2726. ErrorBox('Internal error: there are still '+IntToStr(Bindings^.Count)+' editors '+
  2727. 'registered at TCodeEditorCode.Done!!!',nil);
  2728. {$endif}
  2729. if Assigned(Bindings) then Dispose(Bindings, Done); Bindings:=nil;
  2730. inherited Done;
  2731. end;
  2732. procedure TCustomCodeEditor.Lock;
  2733. begin
  2734. Inc(ELockFlag);
  2735. LockScreenUpdate;
  2736. end;
  2737. procedure TCustomCodeEditor.UnLock;
  2738. begin
  2739. {$ifdef DEBUG}
  2740. if Elockflag=0 then
  2741. Bug('negative lockflag',nil)
  2742. else
  2743. {$endif DEBUG}
  2744. UnlockScreenUpdate;
  2745. Dec(ELockFlag);
  2746. if (ELockFlag>0) then
  2747. Exit;
  2748. if DrawCalled then
  2749. DrawView;
  2750. If DrawCursorCalled then
  2751. Begin
  2752. DrawCursor;
  2753. DrawCursorCalled:=false;
  2754. End;
  2755. end;
  2756. procedure TCustomCodeEditor.DrawIndicator;
  2757. begin
  2758. { Abstract }
  2759. end;
  2760. procedure TCustomCodeEditor.AdjustSelectionPos(OldCurPosX, OldCurPosY: sw_integer; DeltaX, DeltaY: sw_integer);
  2761. var CP: TPoint;
  2762. begin
  2763. if ValidBlock=false then Exit;
  2764. CP.X:=OldCurPosX; CP.Y:=OldCurPosY;
  2765. if (PosToOfsP(SelStart)<=PosToOfsP(CP)) and (PosToOfsP(CP)<PosToOfsP(SelEnd)) then
  2766. begin
  2767. { OldCurPos is IN selection }
  2768. if (CP.Y=SelEnd.Y) then
  2769. begin
  2770. if ((SelStart.Y<>SelEnd.Y) or (SelStart.X<=CP.X)) and
  2771. (CP.X<=SelEnd.X) then
  2772. Inc(SelEnd.X,DeltaX);
  2773. end
  2774. else if (CP.Y=SelEnd.Y+DeltaY) then
  2775. Inc(SelEnd.X,DeltaX);
  2776. Inc(SelEnd.Y,DeltaY);
  2777. SelectionChanged;
  2778. end
  2779. else
  2780. if (PosToOfsP(CP)<=PosToOfsP(SelStart)) then
  2781. begin
  2782. { OldCurPos is BEFORE selection }
  2783. if (CP.Y=SelStart.Y) and (CP.Y=SelEnd.Y) and (DeltaY<0) then
  2784. begin
  2785. SelStart:=CurPos; SelEnd:=CurPos;
  2786. end
  2787. else
  2788. if (CP.Y=SelStart.Y) then
  2789. begin
  2790. if CP.X<SelStart.X then
  2791. Inc(SelStart.X,DeltaX);
  2792. end;
  2793. { else}
  2794. begin
  2795. Inc(SelStart.Y,DeltaY);
  2796. Inc(SelEnd.Y,DeltaY);
  2797. end;
  2798. if SelEnd.Y=CurPos.Y then Inc(SelEnd.X,DeltaX);
  2799. SelectionChanged;
  2800. end
  2801. else
  2802. begin
  2803. { OldCurPos is AFTER selection }
  2804. { actually we don't have to do anything here }
  2805. end;
  2806. end;
  2807. function TCustomCodeEditor.GetFlags: longint;
  2808. begin
  2809. { Abstract }
  2810. GetFlags:=0;
  2811. end;
  2812. procedure TCustomCodeEditor.SetFlags(AFlags: longint);
  2813. begin
  2814. { Abstract }
  2815. end;
  2816. function TCustomCodeEditor.GetModified: boolean;
  2817. begin
  2818. { Abstract }
  2819. GetModified:=true;
  2820. end;
  2821. procedure TCustomCodeEditor.SetModified(AModified: boolean);
  2822. begin
  2823. { Abstract }
  2824. end;
  2825. function TCustomCodeEditor.GetStoreUndo: boolean;
  2826. begin
  2827. { Abstract }
  2828. GetStoreUndo:=false;
  2829. end;
  2830. procedure TCustomCodeEditor.SetStoreUndo(AStore: boolean);
  2831. begin
  2832. { Abstract }
  2833. end;
  2834. function TCustomCodeEditor.GetSyntaxCompleted: boolean;
  2835. begin
  2836. { Abstract }
  2837. GetSyntaxCompleted:=true;
  2838. end;
  2839. procedure TCustomCodeEditor.SetSyntaxCompleted(SC : boolean);
  2840. begin
  2841. { Abstract }
  2842. end;
  2843. function TCustomCodeEditor.GetLastSyntaxedLine: sw_integer;
  2844. begin
  2845. Abstract;
  2846. GetLastSyntaxedLine:=0;
  2847. end;
  2848. procedure TCustomCodeEditor.SetLastSyntaxedLine(ALine: sw_integer);
  2849. begin
  2850. Abstract;
  2851. end;
  2852. function TCustomCodeEditor.IsNestedComments(X,Y : sw_integer): boolean;
  2853. begin
  2854. IsNestedComments:=false; {default behavior is no nested comments}
  2855. end;
  2856. function TCustomCodeEditor.NestedCommentsChangeCheck(CurLine : sw_integer):boolean;
  2857. begin
  2858. NestedCommentsChangeCheck:=false;
  2859. end;
  2860. function TCustomCodeEditor.IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
  2861. begin
  2862. IsFlagSet:=(GetFlags and AFlag)=AFlag;
  2863. end;
  2864. function TCustomCodeEditor.GetTabSize: integer;
  2865. begin
  2866. { Abstract }
  2867. GetTabSize:=5;
  2868. end;
  2869. procedure TCustomCodeEditor.SetTabSize(ATabSize: integer);
  2870. begin
  2871. { Abstract }
  2872. end;
  2873. function TCustomCodeEditor.GetIndentSize: integer;
  2874. begin
  2875. { Abstract }
  2876. GetIndentSize:=1;
  2877. end;
  2878. procedure TCustomCodeEditor.SetIndentSize(AIndentSize: integer);
  2879. begin
  2880. { Abstract }
  2881. end;
  2882. function TCustomCodeEditor.IsReadOnly: boolean;
  2883. begin
  2884. { Abstract }
  2885. IsReadOnly:=false;
  2886. end;
  2887. function TCustomCodeEditor.IsClipboard: Boolean;
  2888. begin
  2889. { Abstract }
  2890. IsClipboard:=false;
  2891. end;
  2892. function TCustomCodeEditor.GetMaxDisplayLength: sw_integer;
  2893. begin
  2894. Abstract;
  2895. GetMaxDisplayLength:=0;
  2896. end;
  2897. function TCustomCodeEditor.GetLineCount: sw_integer;
  2898. begin
  2899. Abstract;
  2900. GetLineCount:=0;
  2901. end;
  2902. function TCustomCodeEditor.GetLine(LineNo: sw_integer): PCustomLine;
  2903. begin
  2904. Abstract;
  2905. GetLine:=nil;
  2906. end;
  2907. function TCustomCodeEditor.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
  2908. begin
  2909. Abstract;
  2910. CharIdxToLinePos:=0;
  2911. end;
  2912. function TCustomCodeEditor.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
  2913. begin
  2914. Abstract;
  2915. LinePosToCharIdx:=0;
  2916. end;
  2917. function TCustomCodeEditor.GetLineText(I: sw_integer): sw_astring;
  2918. begin
  2919. Abstract;
  2920. GetLineText:='';
  2921. end;
  2922. procedure TCustomCodeEditor.SetDisplayText(I: sw_integer;const S: sw_astring);
  2923. begin
  2924. Abstract;
  2925. end;
  2926. function TCustomCodeEditor.GetDisplayText(I: sw_integer): sw_astring;
  2927. begin
  2928. Abstract;
  2929. GetDisplayText:='';
  2930. end;
  2931. procedure TCustomCodeEditor.SetLineText(I: sw_integer;const S: sw_AString);
  2932. begin
  2933. Abstract;
  2934. end;
  2935. procedure TCustomCodeEditor.GetDisplayTextFormat(I: sw_integer;var DT,DF:sw_astring);
  2936. begin
  2937. Abstract;
  2938. end;
  2939. function TCustomCodeEditor.GetLineFormat(I: sw_integer): sw_astring;
  2940. begin
  2941. { Abstract }
  2942. GetLineFormat:='';
  2943. end;
  2944. procedure TCustomCodeEditor.SetLineFormat(I: sw_integer;const S: sw_astring);
  2945. begin
  2946. { Abstract }
  2947. end;
  2948. procedure TCustomCodeEditor.DeleteAllLines;
  2949. begin
  2950. Abstract;
  2951. end;
  2952. procedure TCustomCodeEditor.DeleteLine(I: sw_integer);
  2953. begin
  2954. Abstract;
  2955. end;
  2956. function TCustomCodeEditor.InsertLine(LineNo: sw_integer; const S: sw_astring): PCustomLine;
  2957. begin
  2958. Abstract;
  2959. InsertLine:=nil; { eliminate compiler warning }
  2960. end;
  2961. procedure TCustomCodeEditor.AddLine(const S: sw_astring);
  2962. begin
  2963. Abstract;
  2964. end;
  2965. function TCustomCodeEditor.GetErrorMessage: string;
  2966. begin
  2967. Abstract;
  2968. GetErrorMessage:='';
  2969. end;
  2970. procedure TCustomCodeEditor.SetErrorMessage(const S: string);
  2971. begin
  2972. Abstract;
  2973. end;
  2974. procedure TCustomCodeEditor.GetContent(ALines: PUnsortedStringCollection);
  2975. begin
  2976. Abstract;
  2977. end;
  2978. procedure TCustomCodeEditor.SetContent(ALines: PUnsortedStringCollection);
  2979. begin
  2980. Abstract;
  2981. end;
  2982. function TCustomCodeEditor.LoadFromStream(Stream: PFastBufStream): boolean;
  2983. begin
  2984. Abstract;
  2985. LoadFromStream:=false;
  2986. end;
  2987. function TCustomCodeEditor.SaveToStream(Stream: PStream): boolean;
  2988. var A,B: TPoint;
  2989. begin
  2990. A.Y:=0; A.X:=0;
  2991. B.Y:=GetLineCount-1;
  2992. if GetLineCount>0 then
  2993. B.X:=length(GetDisplayText(B.Y))
  2994. else
  2995. B.X:=0;
  2996. SaveToStream:=SaveAreaToStream(Stream,A,B);
  2997. end;
  2998. function TCustomCodeEditor.SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
  2999. begin
  3000. Abstract;
  3001. SaveAreaToStream:=false;
  3002. end;
  3003. function TCustomCodeEditor.LoadFromFile(const AFileName: string): boolean;
  3004. var S: PFastBufStream;
  3005. OK: boolean;
  3006. begin
  3007. New(S, Init(AFileName,stOpenRead,EditorTextBufSize));
  3008. OK:=Assigned(S);
  3009. {$ifdef TEST_PARTIAL_SYNTAX}
  3010. SetSyntaxCompleted(false);
  3011. { Idle necessary }
  3012. EventMask:=EventMask or evIdle;
  3013. {$endif TEST_PARTIAL_SYNTAX}
  3014. if OK then OK:=LoadFromStream(S);
  3015. if Assigned(S) then Dispose(S, Done);
  3016. LoadFromFile:=OK;
  3017. end;
  3018. function TCustomCodeEditor.SaveToFile(const AFileName: string): boolean;
  3019. var OK: boolean;
  3020. S: PBufStream;
  3021. begin
  3022. New(S, Init(AFileName,stCreate,EditorTextBufSize));
  3023. OK:=Assigned(S) and (S^.Status=stOK);
  3024. if OK then OK:=SaveToStream(S);
  3025. if Assigned(S) then Dispose(S, Done);
  3026. SaveToFile:=OK;
  3027. end;
  3028. procedure TCustomCodeEditor.AdjustBookMark(X, NewX, Y, NewY: sw_integer);
  3029. var P : PEditorBookMark;
  3030. Count,Index : sw_integer;
  3031. Line,NewLine : PCustomLine;
  3032. begin
  3033. if NewY=Y then
  3034. GetLine(Y)^.AdjustMark(@Self,X,NewX-X)
  3035. else
  3036. begin
  3037. Line:=GetLine(Y);
  3038. Count:=Line^.MarkCount(@Self);
  3039. if Count > 0 then
  3040. begin
  3041. NewLine:=GetLine(NewY);
  3042. for Index:=Count-1 downto 0 do
  3043. begin
  3044. P:=Line^.GetMark(@Self,Index);
  3045. if P^.Pos.X>=X then
  3046. begin
  3047. P^.Pos.X:=Max(0,P^.Pos.X+(NewX-X));
  3048. Line^.DeleteMark(@Self,P);
  3049. NewLine^.InsertMark(@Self,P);
  3050. end;
  3051. end;
  3052. end;
  3053. end;
  3054. end;
  3055. function TCustomCodeEditor.InsertFrom(Editor: PCustomCodeEditor): Boolean;
  3056. var OK: boolean;
  3057. CP,CI,RX,RSX,LineDelta,LineCount: Sw_integer;
  3058. StartPos,DestPos,BPos,EPos: TPoint;
  3059. LineStartX,LineEndX: Sw_integer;
  3060. TabSize,CharIdxStart,CharIdxEnd: Sw_integer;
  3061. S,DS,BeforeS,OrigS,AfterS: sw_astring;
  3062. VerticalBlock: boolean;
  3063. SEnd: TPoint;
  3064. begin
  3065. if Editor^.IsFlagSet(efVerticalBlocks) then
  3066. begin
  3067. NotImplemented;
  3068. Exit;
  3069. end;
  3070. Lock;
  3071. { every data in the clipboard gets a new line }
  3072. if (Clipboard=@Self) and (CurPos.X>0) then
  3073. InsertNewLine;
  3074. OK:=(Editor^.SelStart.X<>Editor^.SelEnd.X) or (Editor^.SelStart.Y<>Editor^.SelEnd.Y);
  3075. if OK then
  3076. begin
  3077. if not (Clipboard=@Self) and IsFlagSet(efOverwriteBlocks) and InSelectionArea then
  3078. DelSelect; {delete selection before paste}
  3079. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  3080. CurPos.X:=CharIdxToLinePos(CurPos.Y,CI); {tab space adjustment}
  3081. StartPos:=CurPos; DestPos:=CurPos;
  3082. EPos:=CurPos;
  3083. VerticalBlock:=Editor^.IsFlagSet(efVerticalBlocks);
  3084. LineDelta:=0; LineCount:=(Editor^.SelEnd.Y-Editor^.SelStart.Y)+1;
  3085. OK:=GetLineCount<MaxLineCount;
  3086. OrigS:=GetLineText(DestPos.Y);
  3087. BeforeS:=Copy(OrigS,1,LinePosToCharIdx(DestPos.Y,DestPos.X-1));
  3088. { we might need to add some spaces here,
  3089. but how many ? }
  3090. TabSize:=GetTabSize;
  3091. CP:=1; RX:=0;
  3092. while (CP<=length(BeforeS)) do
  3093. begin
  3094. if (BeforeS[CP]=TAB) then
  3095. Inc(RX,TabSize-(RX mod TabSize))
  3096. else
  3097. Inc(RX);
  3098. Inc(CP);
  3099. end;
  3100. BeforeS:=BeforeS+CharStr(' ',DestPos.X-RX);
  3101. AfterS:=Copy(OrigS,LinePosToCharIdx(DestPos.Y,DestPos.X),Length(OrigS));
  3102. BPos:=CurPos;
  3103. while OK and (LineDelta<LineCount) do
  3104. begin
  3105. S:=Editor^.GetLineText(Editor^.SelStart.Y+LineDelta);
  3106. if (LineDelta>0) and (VerticalBlock=false) then
  3107. begin
  3108. InsertLine(DestPos.Y,'');
  3109. EPOS.X:=0;EPos.Y:=DestPos.Y;
  3110. AddAction(eaInsertLine,BPos,EPos,'',GetFlags);
  3111. LimitsChanged;
  3112. end;
  3113. If LineDelta>0 then
  3114. BeforeS:='';
  3115. if (LineDelta=0) or VerticalBlock then
  3116. LineStartX:=Editor^.SelStart.X
  3117. else
  3118. LineStartX:=0;
  3119. if (LineDelta=LineCount-1) or VerticalBlock then
  3120. begin
  3121. LineEndX:=Editor^.SelEnd.X-1;
  3122. CharIdxEnd:=Editor^.LinePosToCharIdx(Editor^.SelStart.Y+LineDelta,LineEndX);
  3123. end
  3124. else
  3125. begin
  3126. LineEndX:=Length(S);
  3127. CharIdxEnd:=LineEndX;
  3128. end;
  3129. CharIdxStart:=Editor^.LinePosToCharIdx(Editor^.SelStart.Y+LineDelta,LineStartX);
  3130. if LineEndX<LineStartX then
  3131. S:=''
  3132. else if VerticalBlock then
  3133. begin
  3134. S:=copy(S,CharIdxStart,CharIdxEnd-CharIdxStart+1);
  3135. S:=RExpand(S,Min(CharIdxEnd-CharIdxStart+1,Length(S)));
  3136. end else
  3137. S:=copy(S,CharIdxStart,CharIdxEnd-CharIdxStart+1);
  3138. if VerticalBlock=false then
  3139. begin
  3140. DS:=BeforeS+S;
  3141. CP:=1; RX:=0;
  3142. RSX :=0;
  3143. while (CP<=length(DS)) do
  3144. begin
  3145. if (DS[CP]=TAB) then
  3146. Inc(RX,TabSize-(RX mod TabSize))
  3147. else
  3148. Inc(RX);
  3149. if CP=length(BeforeS) then
  3150. RSX:=RX;
  3151. Inc(CP);
  3152. end;
  3153. if LineDelta=LineCount-1 then
  3154. begin
  3155. SetLineText(DestPos.Y,DS+AfterS);
  3156. BPos.X:=DestPos.X;BPos.Y:=DestPos.Y;
  3157. EPOS.X:=DestPos.X+RX-RSX;EPos.Y:=DestPos.Y;
  3158. AddAction(eaInsertText,BPos,EPos,S,GetFlags);
  3159. end
  3160. else
  3161. begin
  3162. SetLineText(DestPos.Y,DS);
  3163. BPos.X:=DestPos.X;BPos.Y:=DestPos.Y;
  3164. EPOS.X:=DestPos.X+RX-RSX;EPos.Y:=DestPos.Y;
  3165. AddAction(eaInsertText,BPos,EPos,S,GetFlags);
  3166. end;
  3167. BPos.X:=EPos.X;
  3168. if LineDelta=LineCount-1 then
  3169. begin
  3170. SEnd.Y:=DestPos.Y;
  3171. SEnd.X:=DestPos.X+RX-RSX;
  3172. end
  3173. else
  3174. begin
  3175. Inc(DestPos.Y);
  3176. DestPos.X:=0;
  3177. end;
  3178. end
  3179. else { if VerticalBlock=false then .. else }
  3180. begin
  3181. { this is not yet implemented !! PM }
  3182. S:=RExpand(S,LineEndX-LineStartX+1);
  3183. end;
  3184. Inc(LineDelta);
  3185. OK:=GetLineCount<MaxLineCount;
  3186. end;
  3187. if not OK then EditorDialog(edTooManyLines,nil);
  3188. { mainly to force eaMove insertion }
  3189. if not IsClipboard then
  3190. SetCurPtr(EPos.X,EPos.Y);
  3191. SetCurPtr(StartPos.X,StartPos.Y);
  3192. UpdateAttrs(StartPos.Y,attrAll);
  3193. SetModified(true);
  3194. LimitsChanged;
  3195. SetSelection(CurPos,SEnd);
  3196. if IsClipboard then
  3197. begin
  3198. Inc(DestPos.X,length(S));
  3199. SetCurPtr(DestPos.X,DestPos.Y);
  3200. end;
  3201. DrawView;
  3202. end;
  3203. UnLock;
  3204. InsertFrom:=OK;
  3205. end;
  3206. function TCustomCodeEditor.InsertText(const S: sw_astring): Boolean;
  3207. var I,CI: sw_integer;
  3208. OldPos: TPoint;
  3209. HoldUndo : boolean;
  3210. WasAutoBrackets : boolean;
  3211. begin
  3212. Lock;
  3213. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  3214. CurPos.X:=CharIdxToLinePos(CurPos.Y,CI); {tab space adjustment}
  3215. OldPos:=CurPos;
  3216. HoldUndo:=GetStoreUndo;
  3217. WasAutoBrackets:=GetAutoBrackets;
  3218. SetAutoBrackets(false);
  3219. SetStoreUndo(false);
  3220. for I:=1 to length(S) do
  3221. AddChar(S[I]);
  3222. InsertText:=true;
  3223. SetAutoBrackets(WasAutoBrackets);
  3224. SetStoreUndo(HoldUndo);
  3225. AddAction(eaInsertText,OldPos,CurPos,S,GetFlags);
  3226. UnLock;
  3227. end;
  3228. procedure TCustomCodeEditor.ModifiedChanged;
  3229. begin
  3230. { Abstract }
  3231. end;
  3232. procedure TCustomCodeEditor.PositionChanged;
  3233. begin
  3234. { Abstract }
  3235. end;
  3236. procedure TCustomCodeEditor.TabSizeChanged;
  3237. begin
  3238. { Abstract }
  3239. end;
  3240. procedure TCustomCodeEditor.SyntaxStateChanged;
  3241. begin
  3242. { Abstract }
  3243. end;
  3244. procedure TCustomCodeEditor.StoreUndoChanged;
  3245. begin
  3246. { Abstract }
  3247. end;
  3248. function TCustomCodeEditor.GetSpecSymbolCount(SpecClass: TSpecSymbolClass): integer;
  3249. begin
  3250. { Abstract }
  3251. GetSpecSymbolCount:=0;
  3252. end;
  3253. function TCustomCodeEditor.GetSpecSymbol(SpecClass: TSpecSymbolClass; Index: integer): pstring;
  3254. begin
  3255. Abstract;
  3256. GetSpecSymbol:=nil;
  3257. end;
  3258. function TCustomCodeEditor.IsReservedWord(const S: string): boolean;
  3259. begin
  3260. { Abstract }
  3261. IsReservedWord:=false;
  3262. end;
  3263. function TCustomCodeEditor.IsAsmReservedWord(const S: string): boolean;
  3264. begin
  3265. { Abstract }
  3266. IsAsmReservedWord:=false;
  3267. end;
  3268. function TCustomCodeEditor.TranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean;
  3269. begin
  3270. { Abstract }
  3271. TranslateCodeTemplate:=false;
  3272. end;
  3273. function TCustomCodeEditor.CompleteCodeWord(const WordS: string; var Text: string): boolean;
  3274. begin
  3275. { Abstract }
  3276. Text:='';
  3277. CompleteCodeWord:=false;
  3278. end;
  3279. function TCustomCodeEditor.GetCodeCompleteWord: string;
  3280. begin
  3281. { Abstract }
  3282. GetCodeCompleteWord:='';
  3283. end;
  3284. function TCustomCodeEditor.CreateFold(StartY,EndY: sw_integer; Collapsed: boolean): boolean;
  3285. var F,ParentF: PFold;
  3286. L: PCustomLine;
  3287. EI: PEditorLineInfo;
  3288. Y: sw_integer;
  3289. OK: boolean;
  3290. begin
  3291. OK:=true;
  3292. Lock;
  3293. for Y:=StartY to EndY do
  3294. begin
  3295. L:=GetLine(Y);
  3296. if assigned(L) then
  3297. EI:=L^.GetEditorInfo(@Self)
  3298. else
  3299. begin
  3300. CreateFold:=False;
  3301. exit;
  3302. end;
  3303. if Y=StartY then
  3304. ParentF:=EI^.Fold
  3305. else
  3306. OK:=OK and (EI^.Fold=ParentF);
  3307. if not OK then
  3308. Break;
  3309. end;
  3310. if OK then
  3311. begin
  3312. New(F, Init(@Self,ParentF,Collapsed));
  3313. for Y:=StartY to EndY do
  3314. GetLine(Y)^.GetEditorInfo(@Self)^.SetFold(F);
  3315. DrawView;
  3316. end;
  3317. UnLock;
  3318. CreateFold:=OK;
  3319. end;
  3320. procedure TCustomCodeEditor.FoldChanged(Fold: PFold);
  3321. var F: PFold;
  3322. I: sw_integer;
  3323. begin
  3324. for I:=0 to GetFoldCount-1 do
  3325. begin
  3326. F:=GetFold(I);
  3327. if F^.ParentFold=Fold then
  3328. FoldChanged(F);
  3329. end;
  3330. if Fold^.IsCollapsed then
  3331. begin
  3332. F:=GetLineFold(CurPos.Y); I:=CurPos.Y;
  3333. if F=Fold then
  3334. begin
  3335. while GetLineFold(I-1)=Fold do
  3336. Dec(I);
  3337. if I<>CurPos.Y then
  3338. SetCurPtr(CurPos.X,I);
  3339. end;
  3340. end;
  3341. DrawView;
  3342. end;
  3343. procedure TCustomCodeEditor.RemoveAllFolds;
  3344. var I: sw_integer;
  3345. L: PCustomLine;
  3346. begin
  3347. for I:=0 to GetLineCount-1 do
  3348. begin
  3349. L:=GetLine(I);
  3350. if not assigned(L) then exit;
  3351. with L^ do
  3352. with GetEditorInfo(@Self)^ do
  3353. SetFold(nil);
  3354. end;
  3355. DrawView;
  3356. end;
  3357. { to be called if CurPos has already been changed }
  3358. procedure TCustomCodeEditor.AdjustSelection(DeltaX, DeltaY: sw_integer);
  3359. begin
  3360. AdjustSelectionPos(CurPos.X-DeltaX,CurPos.Y-DeltaY,DeltaX,DeltaY);
  3361. end;
  3362. { to be called if CurPos has not yet been changed }
  3363. procedure TCustomCodeEditor.AdjustSelectionBefore(DeltaX, DeltaY: sw_integer);
  3364. begin
  3365. AdjustSelectionPos(CurPos.X,CurPos.Y,DeltaX,DeltaY);
  3366. end;
  3367. procedure TCustomCodeEditor.TrackCursor(centre:Tcentre);
  3368. var D,CP: TPoint;
  3369. begin
  3370. D:=Delta;
  3371. EditorToViewPoint(D,D); EditorToViewPoint(CurPos,CP);
  3372. if CP.Y<Delta.Y then D.Y:=CP.Y else
  3373. if CP.Y>Delta.Y+Size.Y-1 then D.Y:=CP.Y-Size.Y+1;
  3374. if CP.X<Delta.X then D.X:=CP.X else
  3375. if CP.X>Delta.X+Size.X-1 then D.X:=CP.X-Size.X+1;
  3376. if {((Delta.X<>D.X) or (Delta.Y<>D.Y)) and }centre=do_centre then
  3377. begin
  3378. { loose centering for debugger PM }
  3379. while (CP.Y-D.Y)<(Size.Y div 3) do Dec(D.Y);
  3380. while (CP.Y-D.Y)>2*(Size.Y div 3) do Inc(D.Y);
  3381. end;
  3382. ViewToEditorPoint(D,D);
  3383. if (Delta.X<>D.X) or (Delta.Y<>D.Y) then
  3384. ScrollTo(D.X,D.Y);
  3385. DrawCursor;
  3386. end;
  3387. procedure TCustomCodeEditor.ScrollTo(X, Y: sw_Integer);
  3388. begin
  3389. inherited ScrollTo(X,Y);
  3390. if (HScrollBar=nil) then Delta.X:=Max(X,0);
  3391. if (VScrollBar=nil) then Delta.Y:=Max(Min(Y,GetLineCount-1),0);
  3392. if (HScrollBar=nil) or (VScrollBar=nil) then DrawView;
  3393. end;
  3394. function TCustomCodeEditor.IsModal: boolean;
  3395. var IsM: boolean;
  3396. begin
  3397. IsM:=GetState(sfModal);
  3398. if Assigned(Owner) then
  3399. IsM:=IsM or Owner^.GetState(sfModal);
  3400. IsModal:=IsM;
  3401. end;
  3402. procedure TCustomCodeEditor.FlagsChanged(OldFlags: longint);
  3403. var I: sw_integer;
  3404. begin
  3405. Lock;
  3406. if ((OldFlags xor GetFlags) and efCodeComplete)<>0 then
  3407. ClearCodeCompleteWord;
  3408. SetInsertMode(IsFlagSet(efInsertMode));
  3409. if ((OldFlags xor GetFlags) and efFolds)<>0 then
  3410. if not IsFlagSet(efFolds) then
  3411. RemoveAllFolds;
  3412. if IsFlagSet(efSyntaxHighlight) then
  3413. UpdateAttrs(0,attrAll) else
  3414. for I:=0 to GetLineCount-1 do
  3415. SetLineFormat(I,'');
  3416. DrawView;
  3417. UnLock;
  3418. end;
  3419. procedure TCustomCodeEditor.LimitsChanged;
  3420. begin
  3421. Abstract;
  3422. end;
  3423. procedure TCustomCodeEditor.DoLimitsChanged;
  3424. var DisplayLength : sw_integer;
  3425. begin
  3426. DisplayLength:=((GetMaxDisplayLength+128) shr 6) shl 6;
  3427. DisplayLength:=Min(DisplayLength,MaxLineLength+1);
  3428. SetLimit(DisplayLength,EditorToViewLine(GetLineCount));
  3429. end;
  3430. procedure TCustomCodeEditor.BindingsChanged;
  3431. begin
  3432. { Abstract }
  3433. end;
  3434. procedure TCustomCodeEditor.ContentsChanged;
  3435. begin
  3436. DrawView;
  3437. end;
  3438. procedure TCustomCodeEditor.ConvertEvent(var Event: TEvent);
  3439. var
  3440. Key: Word;
  3441. begin
  3442. if Event.What = evKeyDown then
  3443. begin
  3444. if (Event.KeyShift and kbShift <> 0) and
  3445. (Event.ScanCode >= $47) and (Event.ScanCode <= $51) then
  3446. Event.CharCode := #0;
  3447. Key := Event.KeyCode;
  3448. if KeyState <> 0 then
  3449. begin
  3450. if (Lo(Key) >= $01) and (Lo(Key) <= $1A) then Inc(Key, $40);
  3451. if (Lo(Key) >= $61) and (Lo(Key) <= $7A) then Dec(Key, $20);
  3452. end;
  3453. Key := ScanKeyMap(KeyMap[KeyState], Key);
  3454. if (KeyState<>0) and (Key=0) then
  3455. ClearEvent(Event); { eat second key if unrecognized after ^Q or ^K }
  3456. KeyState := 0;
  3457. if Key <> 0 then
  3458. if Hi(Key) = $FF then
  3459. begin
  3460. KeyState := Lo(Key);
  3461. ClearEvent(Event);
  3462. end
  3463. else
  3464. begin
  3465. Event.What := evCommand;
  3466. Event.Command := Key;
  3467. end;
  3468. end;
  3469. end;
  3470. procedure TCustomCodeEditor.SetLineFlagState(LineNo: sw_integer; Flags: longint; ASet: boolean);
  3471. var L: PCustomLine;
  3472. begin
  3473. { Avoid crashes if file was shorten for instance }
  3474. if LineNo>=GetLineCount then
  3475. exit;
  3476. L:=GetLine(LineNo);
  3477. if Assigned(L) then
  3478. with L^ do
  3479. if ASet then
  3480. SetFlags(GetFlags or Flags)
  3481. else
  3482. SetFlags(GetFlags and not Flags);
  3483. end;
  3484. procedure TCustomCodeEditor.SetLineFlagExclusive(Flags: longint; LineNo: sw_integer);
  3485. var I,Count: sw_integer;
  3486. L: PCustomLine;
  3487. begin
  3488. Lock;
  3489. Count:=GetLineCount;
  3490. for I:=0 to Count-1 do
  3491. begin
  3492. L:=GetLine(I);
  3493. if not assigned(L) then break;
  3494. if I=LineNo then
  3495. L^.SetFlags(L^.GetFlags or Flags)
  3496. else
  3497. L^.SetFlags(L^.GetFlags and (not Flags));
  3498. end;
  3499. UnLock;
  3500. end;
  3501. procedure TCustomCodeEditor.HandleEvent(var Event: TEvent);
  3502. var DontClear : boolean;
  3503. procedure CheckScrollBar(P: PScrollBar; var D: Sw_Integer);
  3504. begin
  3505. if (Event.InfoPtr = P) and (P^.Value <> D) then
  3506. begin
  3507. D := P^.Value;
  3508. DrawView;
  3509. end;
  3510. end;
  3511. procedure GetMousePos(var P: TPoint);
  3512. begin
  3513. MakeLocal(Event.Where,P);
  3514. Inc(P.X,Delta.X); Inc(P.Y,Delta.Y);
  3515. Dec(P.X,GetReservedColCount);
  3516. if P.X<0 then P.X:=0;
  3517. if P.Y<0 then P.Y:=0;
  3518. end;
  3519. type TCCAction = (ccCheck,ccClear,ccDontCare);
  3520. var
  3521. StartP,P,PrevP: TPoint;
  3522. E: TEvent;
  3523. OldEvent : PEvent;
  3524. CCAction: TCCAction;
  3525. begin
  3526. CCAction:=ccClear;
  3527. E:=Event;
  3528. OldEvent:=CurEvent;
  3529. if (E.What and (evMouse or evKeyboard))<>0 then
  3530. CurEvent:=@E;
  3531. if (InASCIIMode=false) or (Event.What<>evKeyDown) then
  3532. if (Event.What<>evKeyDown) or (Event.KeyCode<>kbEnter) or (IsReadOnly=false) then
  3533. if (Event.What<>evKeyDown) or
  3534. ((Event.KeyCode<>kbEnter) and (Event.KeyCode<>kbEsc)) or
  3535. (GetCompleteState<>csOffering) then
  3536. ConvertEvent(Event);
  3537. case Event.What of
  3538. evMouseDown :
  3539. if (Event.Buttons=mbRightButton) then
  3540. begin
  3541. MakeLocal(Event.Where,P); Inc(P.X); Inc(P.Y);
  3542. LocalMenu(P);
  3543. ClearEvent(Event);
  3544. end else
  3545. if (Event.Buttons=mbLeftButton) and not(Event.Double or Event.Triple) then
  3546. begin
  3547. GetMousePos(P);
  3548. StartP:=P;
  3549. SetCurPtr(P.X,P.Y);
  3550. PrevP.X:=-1; { first time previous point is different }
  3551. repeat
  3552. GetMousePos(P);
  3553. if ((P.X<>PrevP.X) or (P.Y<>PrevP.Y)) or (Event.What = evMouseWheel) then
  3554. begin
  3555. Lock;
  3556. if Event.What = evMouseWheel then
  3557. begin
  3558. E:=Event;
  3559. HandleEvent(Event); { do scrolling }
  3560. Event:=E;
  3561. GetMousePos(P); { new mouse position after scroll up/down }
  3562. end;
  3563. SetCurPtr(P.X,P.Y);
  3564. PrevP:=P;
  3565. if PointOfs(P)<PointOfs(StartP)
  3566. then SetSelection(P,StartP)
  3567. else if PointOfs(P)>PointOfs(StartP)
  3568. then SetSelection(StartP,P)
  3569. else if PointOfs(SelStart)<>PointOfs(SelEnd) { if selected only then remove selection }
  3570. then SetSelection(StartP,P);
  3571. DrawView;
  3572. UnLock;
  3573. end;
  3574. until not MouseEvent(Event, evMouseMove+evMouseAuto+evMouseWheel);
  3575. DrawView;
  3576. ClearEvent(Event);
  3577. end else
  3578. if (Event.Buttons=mbLeftButton) and (Event.Double) then
  3579. begin
  3580. SelectWord;
  3581. ClearEvent(Event);
  3582. end else
  3583. if (Event.Buttons=mbLeftButton) and (Event.Triple) then
  3584. begin
  3585. SelectLine;
  3586. ClearEvent(Event);
  3587. end;
  3588. evKeyDown :
  3589. begin
  3590. { Scancode is almost never zero PM }
  3591. { this is supposed to enable entering of ASCII chars below 32,
  3592. which are normally interpreted as control chars. So, when you enter
  3593. Alt+24 (on the numeric pad) then this will normally move the cursor
  3594. one line down, but if you do it in ASCII mode (also after Ctrl+B)
  3595. then this will insert the ASCII #24 AnsiChar (upper arrow) in the
  3596. source code. - Gabor }
  3597. if InASCIIMode {and (Event.CharCode<>0)} then
  3598. begin
  3599. AddChar(Event.CharCode);
  3600. if (GetCompleteState<>csDenied) or (Event.CharCode=#32) then
  3601. CCAction:=ccCheck
  3602. else
  3603. CCAction:=ccClear;
  3604. end
  3605. else
  3606. begin
  3607. DontClear:=false;
  3608. case Event.KeyCode of
  3609. kbAltF10 :
  3610. Message(@Self,evCommand,cmLocalMenu,@Self);
  3611. kbEnter :
  3612. if IsReadOnly then
  3613. DontClear:=true else
  3614. if GetCompleteState=csOffering then
  3615. CodeCompleteApply
  3616. else
  3617. Message(@Self,evCommand,cmNewLine,nil);
  3618. kbEsc :
  3619. if GetCompleteState=csOffering then
  3620. CodeCompleteCancel else
  3621. if IsModal then
  3622. DontClear:=true;
  3623. else
  3624. case Event.CharCode of
  3625. #9,#32..#255 :
  3626. if (Event.CharCode=#9) and IsModal then
  3627. DontClear:=true
  3628. else
  3629. begin
  3630. NoSelect:=true;
  3631. AddChar(Event.CharCode);
  3632. NoSelect:=false;
  3633. if (GetCompleteState<>csDenied) or (Event.CharCode=#32) then
  3634. CCAction:=ccCheck
  3635. else
  3636. CCAction:=ccClear;
  3637. end;
  3638. else
  3639. DontClear:=true;
  3640. end; { case Event.CharCode .. }
  3641. end; { case Event.KeyCode .. }
  3642. if not DontClear then
  3643. ClearEvent(Event);
  3644. end;
  3645. InASCIIMode:=false;
  3646. end;
  3647. evCommand :
  3648. begin
  3649. DontClear:=false;
  3650. case Event.Command of
  3651. cmASCIIChar : InASCIIMode:=not InASCIIMode;
  3652. cmAddChar : AddChar(chr(longint(Event.InfoPtr)));
  3653. cmCharLeft : CharLeft;
  3654. cmCharRight : CharRight;
  3655. cmWordLeft : WordLeft;
  3656. cmWordRight : WordRight;
  3657. cmLineStart : LineStart;
  3658. cmLineEnd : LineEnd;
  3659. cmLineUp : LineUp;
  3660. cmLineDown : LineDown;
  3661. cmPageUp : PageUp;
  3662. cmPageDown : PageDown;
  3663. cmScrollOneUp : ScrollOneUp;
  3664. cmScrollOneDown:ScrollOneDown;
  3665. cmTextStart : TextStart;
  3666. cmTextEnd : TextEnd;
  3667. cmWindowStart : WindowStart;
  3668. cmWindowEnd : WindowEnd;
  3669. cmNewLine : begin
  3670. InsertNewLine;
  3671. TrackCursor(do_not_centre);
  3672. end;
  3673. cmBreakLine : BreakLine;
  3674. cmBackSpace : BackSpace;
  3675. cmDelChar : DelChar;
  3676. cmDelWord : DelWord;
  3677. cmDelToEndOfWord : DelToEndOfWord;
  3678. cmDelStart : DelStart;
  3679. cmDelEnd : DelEnd;
  3680. cmDelLine : DelLine;
  3681. cmInsMode : InsMode;
  3682. cmStartSelect : StartSelect;
  3683. cmHideSelect : HideSelect;
  3684. cmUpdateTitle : ;
  3685. cmEndSelect : EndSelect;
  3686. cmDelSelect : DelSelect;
  3687. cmCopyBlock : CopyBlock;
  3688. cmMoveBlock : MoveBlock;
  3689. cmIndentBlock : IndentBlock;
  3690. cmUnindentBlock : UnindentBlock;
  3691. cmSelStart : JumpSelStart;
  3692. cmSelEnd : JumpSelEnd;
  3693. cmLastCursorPos : JumpToLastCursorPos;
  3694. cmFindMatchingDelimiter : FindMatchingDelimiter(true);
  3695. cmFindMatchingDelimiterBack : FindMatchingDelimiter(false);
  3696. cmUpperCase : UpperCase;
  3697. cmLowerCase : LowerCase;
  3698. cmWordLowerCase : WordLowerCase;
  3699. cmWordUpperCase : WordUpperCase;
  3700. cmInsertOptions : InsertOptions;
  3701. cmToggleCase : ToggleCase;
  3702. cmCreateFold : CreateFoldFromBlock;
  3703. cmToggleFold : ToggleFold;
  3704. cmExpandFold : ExpandFold;
  3705. cmCollapseFold : CollapseFold;
  3706. cmJumpMark0..cmJumpMark9 : JumpMark(Event.Command-cmJumpMark0);
  3707. cmSetMark0..cmSetMark9 : DefineMark(Event.Command-cmSetMark0);
  3708. cmSelectWord : SelectWord;
  3709. cmSelectLine : SelectLine;
  3710. cmWriteBlock : WriteBlock;
  3711. cmReadBlock : ReadBlock;
  3712. cmPrintBlock : PrintBlock;
  3713. { ------ }
  3714. cmFind : Find;
  3715. cmReplace : Replace;
  3716. cmSearchAgain : DoSearchReplace;
  3717. cmJumpLine : GotoLine;
  3718. { ------ }
  3719. cmCut : ClipCut;
  3720. cmCopy : ClipCopy;
  3721. cmPaste : ClipPaste;
  3722. cmPasteText : PasteText(Event.InfoPtr,Event.Id);
  3723. cmSelectAll : SelectAll(true);
  3724. cmUnselect : SelectAll(false);
  3725. cmCommentSel : CommentSel;
  3726. cmUnCommentSel: UnCommentSel;
  3727. {$ifdef WinClipSupported}
  3728. cmCopyWin : ClipCopyWin;
  3729. cmPasteWin : ClipPasteWin;
  3730. {$endif WinClipSupported}
  3731. cmUndo : Undo;
  3732. cmRedo : Redo;
  3733. cmClear : DelSelect;
  3734. cmExpandCodeTemplate: ExpandCodeTemplate;
  3735. cmLocalMenu :
  3736. begin
  3737. P:=CurPos; Inc(P.X); Inc(P.Y);
  3738. LocalMenu(P);
  3739. end;
  3740. cmActivateMenu :
  3741. Message(Application,evCommand,cmMenu,nil);
  3742. else
  3743. begin
  3744. DontClear:=true;
  3745. CCAction:=ccDontCare;
  3746. end;
  3747. end;
  3748. if DontClear=false then
  3749. ClearEvent(Event);
  3750. end;
  3751. {$ifdef TEST_PARTIAL_SYNTAX}
  3752. evIdle :
  3753. begin
  3754. CCAction:=ccDontCare;
  3755. { Complete syntax by 20 lines increment }
  3756. { could already be quite lengthy on slow systems }
  3757. if not GetSyntaxCompleted then
  3758. UpdateAttrsRange(GetLastSyntaxedLine,GetLastSyntaxedLine+20,AttrAll);
  3759. end;
  3760. {$endif TEST_PARTIAL_SYNTAX}
  3761. evBroadcast :
  3762. begin
  3763. CCAction:=ccDontCare;
  3764. case Event.Command of
  3765. cmUpdate :
  3766. Update;
  3767. cmClearLineHighlights :
  3768. SetLineFlagExclusive(lfHighlightRow,-1);
  3769. cmResetDebuggerRow :
  3770. SetLineFlagExclusive(lfDebuggerRow,-1);
  3771. cmScrollBarChanged:
  3772. if (Event.InfoPtr = HScrollBar) or
  3773. (Event.InfoPtr = VScrollBar) then
  3774. begin
  3775. CheckScrollBar(HScrollBar, Delta.X);
  3776. CheckScrollBar(VScrollBar, Delta.Y);
  3777. end;
  3778. end;
  3779. end;
  3780. else CCAction:=ccDontCare;
  3781. end;
  3782. inherited HandleEvent(Event);
  3783. CurEvent:=OldEvent;
  3784. case CCAction of
  3785. ccCheck : CodeCompleteCheck;
  3786. ccClear : ClearCodeCompleteWord;
  3787. end;
  3788. end;
  3789. procedure TCustomCodeEditor.UpdateUndoRedo(cm : word; action : byte);
  3790. var UndoMenu : PMenuItem;
  3791. begin
  3792. UndoMenu:=PAdvancedMenuBar(MenuBar)^.GetMenuItem(cm);
  3793. if assigned(UndoMenu) then
  3794. begin
  3795. If assigned(UndoMenu^.Param) then
  3796. DisposeStr(UndoMenu^.Param);
  3797. if action<lastaction then
  3798. UndoMenu^.Param:=NewStr(ActionString[action]);
  3799. end;
  3800. end;
  3801. procedure TCustomCodeEditor.Update;
  3802. begin
  3803. Lock;
  3804. LimitsChanged;
  3805. SelectionChanged;
  3806. HighlightChanged;
  3807. UnLock;
  3808. end;
  3809. function TCustomCodeEditor.GetLocalMenu: PMenu;
  3810. begin
  3811. GetLocalMenu:=nil;
  3812. end;
  3813. function TCustomCodeEditor.GetCommandTarget: PView;
  3814. begin
  3815. GetCommandTarget:=@Self;
  3816. end;
  3817. function TCustomCodeEditor.CreateLocalMenuView(var Bounds: TRect; M: PMenu): PMenuPopup;
  3818. var MV: PMenuPopup;
  3819. begin
  3820. New(MV, Init(Bounds, M));
  3821. CreateLocalMenuView:=MV;
  3822. end;
  3823. procedure TCustomCodeEditor.LocalMenu(P: TPoint);
  3824. var M: PMenu;
  3825. MV: PMenuPopUp;
  3826. R: TRect;
  3827. Re: word;
  3828. begin
  3829. M:=GetLocalMenu;
  3830. if M=nil then Exit;
  3831. if LastLocalCmd<>0 then
  3832. M^.Default:=SearchMenuItem(M,LastLocalCmd);
  3833. Desktop^.GetExtent(R);
  3834. MakeGlobal(P,R.A); {Desktop^.MakeLocal(R.A,R.A);}
  3835. MV:=CreateLocalMenuView(R,M);
  3836. Re:=Application^.ExecView(MV);
  3837. if M^.Default=nil then LastLocalCmd:=0
  3838. else LastLocalCmd:=M^.Default^.Command;
  3839. Dispose(MV, Done);
  3840. if Re<>0 then
  3841. Message(GetCommandTarget,evCommand,Re,@Self);
  3842. end;
  3843. function TCustomCodeEditor.GetReservedColCount: sw_integer;
  3844. var LSX: sw_integer;
  3845. begin
  3846. if IsFlagSet(efFolds) then LSX:=GetFoldStringWidth else LSX:=0;
  3847. GetReservedColCount:=LSX;
  3848. end;
  3849. procedure TCustomCodeEditor.Draw;
  3850. function GetEIFold(EI: PEditorLineInfo): PFold;
  3851. begin
  3852. if Assigned(EI) then GetEIFold:=EI^.Fold else GetEIFold:=nil;
  3853. end;
  3854. var SelectColor,
  3855. HighlightColColor,
  3856. HighlightRowColor,
  3857. ErrorMessageColor : word;
  3858. B: TDrawBuffer;
  3859. X,Y,AX,AY,MaxX,LSX: sw_integer;
  3860. PX: TPoint;
  3861. LineCount: sw_integer;
  3862. Line: PCustomLine;
  3863. LineText,Format: sw_astring;
  3864. isBreak : boolean;
  3865. C: AnsiChar;
  3866. FreeFormat: array[0..MaxLineLength] of boolean;
  3867. Color: word;
  3868. ColorTab: array[coFirstColor..coLastColor] of word;
  3869. ErrorLine: integer;
  3870. {$if MaxViewWidth < 256}
  3871. ErrorMsg: string[MaxViewWidth];
  3872. {$else}
  3873. ErrorMsg: string[255];
  3874. {$endif}
  3875. function CombineColors(Orig,Modifier: byte): byte;
  3876. var Color: byte;
  3877. begin
  3878. if (Modifier and $0f)=0 then
  3879. Color:=(Orig and $0f) or (Modifier and $f0)
  3880. else
  3881. Color:=(Orig and $f0) or (Modifier and $0f);
  3882. { do not allow invisible }
  3883. { use white as foreground in this case }
  3884. if (Color and $f) = ((Color div $10) and $7) then
  3885. Color:=(Color and $F0) or $F;
  3886. CombineColors:=Color;
  3887. end;
  3888. var ShowIndent:boolean;
  3889. FoldPrefix,FoldSuffix: string;
  3890. { SkipLine: boolean;}
  3891. { FoldStartLine: sw_integer;}
  3892. begin
  3893. if ELockFlag>0 then
  3894. begin
  3895. DrawCalled:=true;
  3896. Exit;
  3897. end;
  3898. DrawCalled:=false;
  3899. ErrorMsg:=copy(GetErrorMessage,1,MaxViewWidth);
  3900. if ErrorMsg='' then ErrorLine:=-1 else
  3901. if (CurPos.Y-Delta.Y)<(Size.Y div 2) then ErrorLine:=Size.Y-1
  3902. else ErrorLine:=0;
  3903. LineCount:=GetLineCount;
  3904. ColorTab[coTextColor]:=GetColor(1);
  3905. ColorTab[coWhiteSpaceColor]:=GetColor(2);
  3906. ColorTab[coCommentColor]:=GetColor(3);
  3907. ColorTab[coReservedWordColor]:=GetColor(4);
  3908. ColorTab[coIdentifierColor]:=GetColor(5);
  3909. ColorTab[coStringColor]:=GetColor(6);
  3910. ColorTab[coNumberColor]:=GetColor(7);
  3911. ColorTab[coAssemblerColor]:=GetColor(8);
  3912. ColorTab[coSymbolColor]:=GetColor(9);
  3913. ColorTab[coDirectiveColor]:=GetColor(13);
  3914. ColorTab[coHexNumberColor]:=GetColor(14);
  3915. ColorTab[coTabColor]:=GetColor(15);
  3916. { break same as error }
  3917. ColorTab[coBreakColor]:=GetColor(16);
  3918. ColorTab[coAsmReservedColor]:=GetColor(17);
  3919. SelectColor:=GetColor(10);
  3920. HighlightColColor:=GetColor(11);
  3921. HighlightRowColor:=GetColor(12);
  3922. ErrorMessageColor:=GetColor(16);
  3923. ShowIndent:=IsFlagSet(efShowIndent) and IsFlagSet(efSyntaxHighlight);
  3924. {$ifdef TEST_PARTIAL_SYNTAX}
  3925. If (not GetSyntaxCompleted) and (GetLastSyntaxedLine<Delta.Y+Size.Y) then
  3926. UpdateAttrsRange(GetLastSyntaxedLine,Delta.Y+Size.Y,AttrAll);
  3927. {$endif TEST_PARTIAL_SYNTAX}
  3928. LSX:=GetReservedColCount;
  3929. Y:=0; AY:=Delta.Y;
  3930. for Y:=0 to Size.Y-1 do
  3931. begin
  3932. if Y=ErrorLine then
  3933. begin
  3934. MoveChar(B,' ',ErrorMessageColor,Size.X);
  3935. MoveStr(B,ErrorMsg,ErrorMessageColor);
  3936. WriteLine(0,Y,Size.X,1,B);
  3937. end
  3938. else
  3939. begin
  3940. AY:=ViewToEditorLine(Delta.Y+Y);
  3941. if (0<=AY) and (AY<LineCount) then
  3942. begin
  3943. Line:=GetLine(AY);
  3944. if assigned(Line) then
  3945. begin
  3946. IsBreak:=Line^.IsFlagSet(lfBreakpoint);
  3947. end
  3948. else
  3949. begin
  3950. IsBreak:=false;
  3951. end;
  3952. end
  3953. else
  3954. begin
  3955. Line:=nil;
  3956. IsBreak:=false;
  3957. end;
  3958. begin
  3959. Color:=ColorTab[coTextColor];
  3960. FillChar(FreeFormat,SizeOf(FreeFormat),1);
  3961. { MoveChar(B,' ',Color,Size.X); redundant, following for loop covers it all }
  3962. GetDisplayTextFormat(AY,LineText,Format);
  3963. if ShowIndent and (length(Format)=length(LineText)) then
  3964. for X:=1 to length(LineText) do
  3965. begin
  3966. if LineText[X] <> ' ' then break;
  3967. if (X>1 ) and (X and 1 = 1) then
  3968. if ord(Format[X]) in [coWhiteSpaceColor,coTabColor] then
  3969. LineText[X]:=#179; { | show line indent }
  3970. end;
  3971. MaxX:=Min(Delta.X+1+Size.X,MaxLineLength);
  3972. for X:=(MaxX-Size.X) to MaxX+1 do
  3973. begin
  3974. AX:=Delta.X+X-1;
  3975. if X<=length(LineText) then C:=LineText[X] else C:=' ';
  3976. PX.X:=AX-Delta.X; PX.Y:=AY;
  3977. if (Highlight.A.X<>Highlight.B.X) or (Highlight.A.Y<>Highlight.B.Y) then
  3978. { there's a highlight }
  3979. begin
  3980. if (PointOfs(Highlight.A)<=PointOfs(PX)) and (PointOfs(PX)<PointOfs(Highlight.B)) then
  3981. begin
  3982. Color:=SelectColor;
  3983. FreeFormat[X]:=false;
  3984. end;
  3985. end
  3986. else
  3987. { no highlight }
  3988. begin
  3989. if IsFlagSet(efVerticalBlocks) then
  3990. begin
  3991. if (SelStart.X<=AX) and (AX<=SelEnd.X) and
  3992. (SelStart.Y<=AY) and (AY<=SelEnd.Y) then
  3993. begin
  3994. Color:=SelectColor; FreeFormat[X]:=false;
  3995. end;
  3996. end
  3997. else
  3998. if PointOfs(SelStart)<>PointOfs(SelEnd) then
  3999. if (PointOfs(SelStart)<=PointOfs(PX)) and (PointOfs(PX)<PointOfs(SelEnd)) then
  4000. begin
  4001. Color:=SelectColor; FreeFormat[X]:=false;
  4002. end;
  4003. end; { no highlight }
  4004. if FreeFormat[X] then
  4005. if X<=length(Format) then
  4006. {Color:=ColorTab[ord(Format[X])] else Color:=ColorTab[coTextColor];
  4007. this give BoundsCheckError with -Cr quite often PM }
  4008. Color:=ColorTab[ord(Format[X]) mod (coLastColor + 1)] else Color:=ColorTab[coTextColor];
  4009. if IsFlagSet(efHighlightRow) and
  4010. (PX.Y=CurPos.Y) then
  4011. begin
  4012. Color:=CombineColors(Color,HighlightRowColor);
  4013. FreeFormat[X]:=false;
  4014. end;
  4015. if IsFlagSet(efHighlightColumn) and (PX.X=CurPos.X) then
  4016. begin
  4017. Color:=CombineColors(Color,HighlightColColor);
  4018. FreeFormat[X]:=false;
  4019. end;
  4020. if Assigned(Line) and Line^.IsFlagSet(lfHighlightRow) then
  4021. begin
  4022. Color:=CombineColors(Color,HighlightRowColor);
  4023. FreeFormat[X]:=false;
  4024. end;
  4025. if isbreak then
  4026. begin
  4027. Color:=ColorTab[coBreakColor];
  4028. FreeFormat[X]:=false;
  4029. end;
  4030. if Assigned(Line) and Line^.isFlagSet(lfDebuggerRow) then
  4031. begin
  4032. Color:=CombineColors(Color,HighlightRowColor);
  4033. FreeFormat[X]:=false;
  4034. end;
  4035. { redundant check, for loop condition is taking care of correct range
  4036. if (0<=LSX+X-1-Delta.X) and (LSX+X-1-Delta.X<MaxViewWidth) then }
  4037. MoveChar(B[LSX+X-1-Delta.X],C,Color,1);
  4038. end; { for X:=1 to ... }
  4039. if IsFlagSet(efFolds) then
  4040. begin
  4041. GetFoldStrings(AY,FoldPrefix,FoldSuffix);
  4042. MoveStr(B[0],FoldPrefix,ColorTab[coTextColor]);
  4043. if FoldSuffix<>'' then
  4044. MoveStr(B[Size.X-1-length(FoldSuffix)],FoldSuffix,ColorTab[coTextColor]);
  4045. end;
  4046. WriteLine(0,Y,Size.X,1,B);
  4047. end; { if not SkipLine ... }
  4048. end; { not errorline }
  4049. end; { while (Y<Size.Y) ... }
  4050. DrawCursor;
  4051. end;
  4052. procedure TCustomCodeEditor.DrawCursor;
  4053. var InsertMode : boolean;
  4054. begin
  4055. if Elockflag>0 then
  4056. DrawCursorCalled:=true
  4057. else
  4058. begin
  4059. SetCursor(GetReservedColCount+CurPos.X-Delta.X,EditorToViewLine(CurPos.Y)-Delta.Y);
  4060. InsertMode:=Overwrite;
  4061. if IsFlagSet (efBlockInsCursor) then
  4062. InsertMode:=not InsertMode; {reverse insert and overwrite mode cursor shapes}
  4063. SetState(sfCursorIns,InsertMode);
  4064. end;
  4065. end;
  4066. procedure TCustomCodeEditor.ResetCursor;
  4067. begin
  4068. if Elockflag>0 then
  4069. begin
  4070. DrawCursorCalled:=true;
  4071. exit;
  4072. end
  4073. else
  4074. inherited ResetCursor;
  4075. end;
  4076. function TCustomCodeEditor.Overwrite: boolean;
  4077. begin
  4078. Overwrite:=not IsFlagSet(efInsertMode);
  4079. end;
  4080. procedure TCustomCodeEditor.SetCodeCompleteWord(const S: string);
  4081. begin
  4082. if S<>'' then
  4083. SetCompleteState(csOffering)
  4084. else
  4085. SetCompleteState(csInactive);
  4086. end;
  4087. procedure TCustomCodeEditor.ClearCodeCompleteWord;
  4088. begin
  4089. SetCodeCompleteWord('');
  4090. SetCompleteState(csInactive);
  4091. end;
  4092. function TCustomCodeEditor.GetCompleteState: TCompleteState;
  4093. begin
  4094. { Abstract }
  4095. GetCompleteState:=csInactive;
  4096. end;
  4097. procedure TCustomCodeEditor.SetCompleteState(AState: TCompleteState);
  4098. begin
  4099. { Abstract }
  4100. end;
  4101. function TCustomCodeEditor.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
  4102. begin
  4103. Abstract;
  4104. UpdateAttrs:=-1;
  4105. end;
  4106. function TCustomCodeEditor.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
  4107. begin
  4108. Abstract;
  4109. UpdateAttrsRange:=-1;
  4110. end;
  4111. procedure TCustomCodeEditor.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: sw_astring;AFlags : longint);
  4112. begin
  4113. { Abstract }
  4114. end;
  4115. procedure TCustomCodeEditor.AddGroupedAction(AAction : byte);
  4116. begin
  4117. { Abstract }
  4118. end;
  4119. procedure TCustomCodeEditor.CloseGroupedAction(AAction : byte);
  4120. begin
  4121. { Abstract }
  4122. end;
  4123. function TCustomCodeEditor.GetUndoActionCount: sw_integer;
  4124. begin
  4125. { Abstract }
  4126. GetUndoActionCount:=0;
  4127. end;
  4128. function TCustomCodeEditor.GetRedoActionCount: sw_integer;
  4129. begin
  4130. { Abstract }
  4131. GetRedoActionCount:=0;
  4132. end;
  4133. function TCustomCodeEditor.GetMaxFoldLevel: sw_integer;
  4134. var Max,L,I: sw_integer;
  4135. begin
  4136. Max:=0;
  4137. for I:=0 to GetFoldCount-1 do
  4138. begin
  4139. L:=GetFold(I)^.GetLevel;
  4140. if L>Max then Max:=L;
  4141. end;
  4142. GetMaxFoldLevel:=Max;
  4143. end;
  4144. function TCustomCodeEditor.GetFoldStringWidth: sw_integer;
  4145. begin
  4146. GetFoldStringWidth:=GetMaxFoldLevel;
  4147. end;
  4148. procedure TCustomCodeEditor.GetFoldStrings(EditorLine: sw_integer; var Prefix, Suffix: openstring);
  4149. var F: PFold;
  4150. C: AnsiChar;
  4151. begin
  4152. Prefix:=CharStr(' ',GetFoldStringWidth); Suffix:='';
  4153. F:=GetLineFold(EditorLine);
  4154. if Assigned(F) then
  4155. begin
  4156. if F^.Collapsed_ then C:=#27 else C:=#26;
  4157. Prefix[1+F^.GetLevel]:=C;
  4158. if F^.Collapsed_ then
  4159. Suffix:='('+IntToStr(F^.GetLineCount)+')';
  4160. end;
  4161. end;
  4162. function TCustomCodeEditor.GetFoldCount: sw_integer;
  4163. begin
  4164. GetFoldCount:=0;
  4165. end;
  4166. function TCustomCodeEditor.GetFold(Index: sw_integer): PFold;
  4167. begin
  4168. GetFold:=nil;
  4169. end;
  4170. procedure TCustomCodeEditor.RegisterFold(AFold: PFold);
  4171. begin
  4172. Abstract;
  4173. end;
  4174. procedure TCustomCodeEditor.UnRegisterFold(AFold: PFold);
  4175. begin
  4176. Abstract;
  4177. end;
  4178. procedure TCustomCodeEditor.Indent;
  4179. var S, PreS: sw_astring;
  4180. Shift: integer;
  4181. begin
  4182. S:=GetLineText(CurPos.Y);
  4183. if CurPos.Y>0 then
  4184. PreS:=RTrim(GetLineText(CurPos.Y-1),not IsFlagSet(efUseTabCharacters))
  4185. else
  4186. PreS:='';
  4187. if CurPos.X>=length(PreS) then
  4188. Shift:=GetTabSize
  4189. else
  4190. begin
  4191. Shift:=1;
  4192. while (CurPos.X+Shift<length(PreS)) and (PreS[CurPos.X+Shift]<>' ') do
  4193. Inc(Shift);
  4194. end;
  4195. SetLineText(CurPos.Y,RExpand(copy(S,1,CurPos.X+1),CurPos.X+1)+CharStr(' ',Shift)+copy(S,CurPos.X+2,Length(S)));
  4196. SetCurPtr(CurPos.X+Shift,CurPos.Y);
  4197. UpdateAttrs(CurPos.Y,attrAll);
  4198. DrawLines(CurPos.Y);
  4199. SetModified(true);
  4200. end;
  4201. procedure TCustomCodeEditor.CharLeft;
  4202. begin
  4203. if CurPos.X=0 then Exit;
  4204. SetCurPtr(CurPos.X-1,CurPos.Y);
  4205. end;
  4206. procedure TCustomCodeEditor.CharRight;
  4207. begin
  4208. if CurPos.X>=MaxLineLength then
  4209. Exit;
  4210. SetCurPtr(CurPos.X+1,CurPos.Y);
  4211. end;
  4212. procedure TCustomCodeEditor.WordLeft;
  4213. var X, Y: sw_integer;
  4214. Line: sw_astring;
  4215. GotIt,FoundNonSeparator: boolean;
  4216. N,orgX : sw_integer;
  4217. WhiteSpaceLen : sw_word;
  4218. EnhancedStops : boolean;
  4219. begin
  4220. EnhancedStops:=IsFlagSet(efEnhWordRightLeft);
  4221. X:=CurPos.X;
  4222. Y:=CurPos.Y;
  4223. orgX:=X;
  4224. GotIt:=false;
  4225. FoundNonSeparator:=false;
  4226. while (Y>=0) do
  4227. begin
  4228. X:=length(GetDisplayText(Y));
  4229. if Y=CurPos.Y then
  4230. if CurPos.X<X then
  4231. X:=CurPos.X;
  4232. Dec(X);
  4233. if (X=-1) then {at very beginning of line, go to prev line}
  4234. begin
  4235. while true do { skip all empyt lines }
  4236. begin
  4237. Dec(Y);
  4238. if Y>=0 then
  4239. X:=length(GetDisplayText(Y));
  4240. if (X >0) or (Y<=0) then
  4241. Break;
  4242. if not EnhancedStops then
  4243. break; {stop even at empty lines (TP compatibility)}
  4244. end;
  4245. break;
  4246. end;
  4247. Line:=GetDisplayText(Y);
  4248. if Y<>CurPos.Y then
  4249. orgX:=X;
  4250. WhiteSpaceLen:=0; {Count leading white spaces}
  4251. if (Length(Line)>=X+1) then
  4252. while (X>=WhiteSpaceLen) do
  4253. begin
  4254. if not (Line[WhiteSpaceLen+1] in [' ',#9]) then
  4255. break;
  4256. inc(WhiteSpaceLen);
  4257. end;
  4258. if WhiteSpaceLen>X then
  4259. X:=-1; { moving to next line }
  4260. while (X>=0) and (GotIt=false) do
  4261. begin
  4262. if EnhancedStops and (WhiteSpaceLen=0) and (X=0) and (orgX>0) then
  4263. begin
  4264. GotIt:=true; {stop at very beginning of line, if no white space}
  4265. break;
  4266. end;
  4267. if EnhancedStops and (WhiteSpaceLen = X+1) then
  4268. begin
  4269. GotIt:=true; {stop before leading white space}
  4270. inc(X);
  4271. break;
  4272. end;
  4273. if FoundNonSeparator then
  4274. begin
  4275. if IsWordSeparator(Line[X+1]) then
  4276. begin
  4277. Inc(X);
  4278. GotIt:=true;
  4279. Break;
  4280. end;
  4281. end
  4282. else
  4283. if not IsWordSeparator(Line[X+1]) then
  4284. FoundNonSeparator:=true
  4285. else if EnhancedStops then
  4286. begin
  4287. { stop on comment start, comment end }
  4288. if Line[X+1] in ['(','*',')','/','{','}'] then
  4289. begin
  4290. (* comment } at end of line *)
  4291. if (Length(line)=X+1) and (X<orgX-1) then
  4292. if (Line[X+1] = '}') then
  4293. begin
  4294. GotIt:=true;
  4295. inc(X,2);
  4296. end;
  4297. (* comment { at end of line or right in front of cursor *)
  4298. if (Length(line)=X+1) and (X<=orgX-1) then
  4299. if (Line[X+1] = '{') and ((X=0) or ((X>1) and (Line[X]<>'{'))) then
  4300. begin
  4301. GotIt:=true;
  4302. inc(X,1);
  4303. end;
  4304. if X<orgX then
  4305. if Length(line)>=X+2 then
  4306. if ((Line[X+1] = '/') and (Line[X+2] = '/'))
  4307. or ((Line[X+1] = '(') and (Line[X+2] = '*'))
  4308. or ((Line[X+1] = '*') and (Line[X+2] = ')'))
  4309. or ((Line[X+1] = '{') and (Line[X+2] <> '{') and ((X=0) or ((X>0) and (Line[X] <> '{') )))
  4310. or ((Line[X+1] = '}') and (Line[X+2] <> '}'))
  4311. or ((Line[X+1] = '{') and (X>0) and (Line[X] <> '{'))
  4312. then
  4313. begin
  4314. GotIt:=true;
  4315. (* comment } *)
  4316. if GotIt and (Line[X+1] = '}') then
  4317. if (X<orgX-1) then
  4318. Inc(X,1)
  4319. else
  4320. GotIt:=false;
  4321. { comment *) }
  4322. if GotIt and (Line[X+1] = '*') then
  4323. if (X<orgX-2) then
  4324. Inc(X,2)
  4325. else
  4326. GotIt:=false;
  4327. { comment // }
  4328. if Line[X+1] = '/' then
  4329. for N:=1 to X do
  4330. if (Line[N] = '/') and (Line[N+1] = '/') then
  4331. begin
  4332. GotIt:=false;
  4333. break;
  4334. end;
  4335. if GotIt then
  4336. Inc(X);
  4337. end;
  4338. end; { of comment stop }
  4339. end;
  4340. Dec(X);
  4341. if (X=0) and (IsWordSeparator(Line[1])=false) then
  4342. begin
  4343. GotIt:=true;
  4344. Break;
  4345. end;
  4346. end;
  4347. if GotIt then
  4348. Break;
  4349. X:=0;
  4350. Dec(Y);
  4351. if Y>=0 then
  4352. begin
  4353. X:=length(GetDisplayText(Y));
  4354. if X>0 then
  4355. Break;
  4356. if not EnhancedStops then
  4357. break; {stop even at empty lines (TP compatibility)}
  4358. end;
  4359. orgX:=X;
  4360. end;
  4361. if Y<0 then Y:=0; if X<0 then X:=0;
  4362. SetCurPtr(X,Y);
  4363. end;
  4364. procedure TCustomCodeEditor.WordRight;
  4365. var X, Y: sw_integer;
  4366. Line: sw_astring;
  4367. GotIt: boolean;
  4368. N : sw_integer;
  4369. EnhancedStops : boolean;
  4370. begin
  4371. EnhancedStops:=IsFlagSet(efEnhWordRightLeft);
  4372. X:=CurPos.X; Y:=CurPos.Y; GotIt:=false;
  4373. while (Y<GetLineCount) do
  4374. begin
  4375. if Y=CurPos.Y then
  4376. begin
  4377. X:=CurPos.X; Inc(X);
  4378. if (X>length(GetDisplayText(Y))) then
  4379. begin
  4380. Inc(Y);
  4381. X:=0;
  4382. end;
  4383. end else X:=0;
  4384. Line:=GetDisplayText(Y);
  4385. N:=X;
  4386. if N<1 then N:=1;
  4387. if EnhancedStops and (N<=length(Line)) and (Line[N] = ' ') then {sepcial exception if line beginning contains only spaces then we stop at the beginning of word (not at end)}
  4388. begin
  4389. N:=1;
  4390. {count spaces in beginning of line}
  4391. while (Y<GetLineCount) and (N<=length(Line)) and (Line[N] = ' ') do
  4392. begin
  4393. if N>=length(Line) then
  4394. break;
  4395. inc(N);
  4396. end;
  4397. {if not IsWordSeparator(Line[N]) then }
  4398. if X<N then {special case detected, stop at first non white space character}
  4399. begin X:=N; dec(X); GotIt:=true; break; end;
  4400. end;
  4401. if not EnhancedStops then { skip current word }
  4402. begin
  4403. if (X=0) and (Length(Line)>0) then
  4404. inc(X);
  4405. while (X<=length(Line)) and (GotIt=false) and (Line<>'') do
  4406. begin
  4407. if IsWordSeparator(Line[X]) then break;
  4408. Inc(X);
  4409. end;
  4410. end;
  4411. { find end of word (if EnhancedStops=false then beginning of word) }
  4412. while (X<=length(Line)+1) and (GotIt=false) and (Line<>'') do
  4413. begin
  4414. if X=length(Line)+1 then {end of line found }
  4415. begin
  4416. GotIt:=true;
  4417. Dec(X);
  4418. Break
  4419. end;
  4420. if (X>0) and (not IsWordSeparator(Line[X])) then
  4421. begin
  4422. if not EnhancedStops then { stop at beginning of word }
  4423. begin GotIt:=true; Dec(X); Break; end;
  4424. while (Y<GetLineCount) and (X<=length(Line)) and not (IsWordSeparator(Line[X])) do
  4425. begin
  4426. Inc(X);
  4427. if X>length(Line) then
  4428. begin GotIt:=true; Dec(X); Break; end;
  4429. end;
  4430. if (GotIt=false) and (X<=length(Line)) then
  4431. begin Dec(X); GotIt:=true; Break; end;
  4432. end
  4433. else if EnhancedStops then
  4434. begin
  4435. { stop on comment start, comment end }
  4436. (* comment } *)
  4437. if (X>0) and (Line[X] = '}') then
  4438. if X<length(Line) then
  4439. if (Line[X+1] <> '}') then
  4440. GotIt:=true;
  4441. { comment *) cursor on ")"}
  4442. if ((X>1)and (Line[X-1] = '*') and (Line[X] = ')')) then
  4443. GotIt:=true;
  4444. if not GotIt and (Line[X+1] in ['(','*',')','/','{']) then
  4445. begin
  4446. (* comment "{" *)
  4447. if (Line[X+1] = '{') then
  4448. begin
  4449. if X>0 then
  4450. if (Line[X] <> '{') then
  4451. GotIt:=true;
  4452. if X = 0 then
  4453. GotIt:=true;
  4454. end;
  4455. { comments // (* *) }
  4456. if (Length(Line)>=X+2) then
  4457. if ((Line[X+1] = '/') and (Line[X+2] = '/'))
  4458. or ((Line[X+1] = '(') and (Line[X+2] = '*'))
  4459. or ((Line[X+1] = '*') and (Line[X+2] = ')'))
  4460. or ((X>0)and (Line[X] = '*') and (Line[X+1] = ')')) then
  4461. begin
  4462. GotIt:=true;
  4463. if ((X>0)and (Line[X] = '*') and (Line[X+1] = ')')) then
  4464. inc(X,1);
  4465. if ((Line[X+1] = '*') and (Line[X+2] = ')')) then
  4466. inc(X,2);
  4467. if Line[X+1] = '/' then
  4468. for N:=1 to X do
  4469. if (Line[N] = '/') and (Line[N+1] = '/') then
  4470. begin
  4471. GotIt:=false; {there was line comment before }
  4472. break;
  4473. end;
  4474. end;
  4475. end; { of comment stop }
  4476. end;
  4477. if GotIt then Break;
  4478. Inc(X);
  4479. end;
  4480. if GotIt then Break;
  4481. {next line}
  4482. X:=0;
  4483. Inc(Y);
  4484. if (Y<GetLineCount) then
  4485. begin
  4486. Line:=GetDisplayText(Y);
  4487. if (Line<>'') and (IsWordSeparator(Line[1])=false) then
  4488. Break;
  4489. end;
  4490. end;
  4491. if Y=GetLineCount then Y:=GetLineCount-1;
  4492. SetCurPtr(X,Y);
  4493. end;
  4494. procedure TCustomCodeEditor.LineStart;
  4495. begin
  4496. SetCurPtr(0,CurPos.Y);
  4497. end;
  4498. procedure TCustomCodeEditor.LineEnd;
  4499. var
  4500. s : sw_astring;
  4501. i : longint;
  4502. begin
  4503. if CurPos.Y<GetLineCount then
  4504. begin
  4505. s:=GetDisplayText(CurPos.Y);
  4506. i:=length(s);
  4507. while (i>0) and (s[i]=' ') do
  4508. dec(i);
  4509. i:=Min(i,MaxLineLength);
  4510. SetCurPtr(i,CurPos.Y);
  4511. end
  4512. else
  4513. SetCurPtr(0,CurPos.Y);
  4514. end;
  4515. function TCustomCodeEditor.NextVisibleLine(StartLine: sw_integer; Down: boolean): sw_integer;
  4516. var Count,NL: sw_integer;
  4517. begin
  4518. if Down then
  4519. begin
  4520. Count:=GetLineCount;
  4521. NL:=StartLine;
  4522. while (NL<Count-1) and not IsLineVisible(NL) do
  4523. Inc(NL);
  4524. if NL>=Count then
  4525. NL:=-1;
  4526. end
  4527. else
  4528. begin
  4529. NL:=StartLine;
  4530. while (NL>0) and not IsLineVisible(NL) do
  4531. Dec(NL);
  4532. end;
  4533. if not IsLineVisible(NL) then
  4534. NL:=-1;
  4535. NextVisibleLine:=NL;
  4536. end;
  4537. procedure TCustomCodeEditor.LineUp;
  4538. var NL: sw_integer;
  4539. begin
  4540. NL:=NextVisibleLine(CurPos.Y-1,false);
  4541. if NL<>-1 then
  4542. SetCurPtr(CurPos.X,NL);
  4543. end;
  4544. procedure TCustomCodeEditor.LineDown;
  4545. var NL: sw_integer;
  4546. begin
  4547. NL:=NextVisibleLine(CurPos.Y+1,true);
  4548. if NL<>-1 then
  4549. SetCurPtr(CurPos.X,NL);
  4550. end;
  4551. procedure TCustomCodeEditor.PageUp;
  4552. var NL: sw_integer;
  4553. begin
  4554. ScrollTo(Delta.X,Max(Delta.Y-Size.Y,0));
  4555. NL:=Max(CurPos.Y-(Size.Y),0);
  4556. if not IsLineVisible(NL) then
  4557. NL:=NextVisibleLine(NL,false);
  4558. if NL>=0 then
  4559. SetCurPtr(CurPos.X,Max(0,NL));
  4560. end;
  4561. procedure TCustomCodeEditor.PageDown;
  4562. var NL: sw_integer;
  4563. begin
  4564. ScrollTo(Delta.X,Min(Delta.Y+Size.Y,GetLineCount-1));
  4565. NL:=Min(CurPos.Y+(Size.Y{-1}),GetLineCount-1);
  4566. if not IsLineVisible(NL) then
  4567. NL:=NextVisibleLine(NL,true);
  4568. if NL>=0 then
  4569. SetCurPtr(CurPos.X,Min(GetLineCount-1,NL));
  4570. end;
  4571. procedure TCustomCodeEditor.ScrollOneUp;
  4572. var NL: sw_integer;
  4573. LinesScroll : sw_integer;
  4574. cursorInVisibleArea : boolean;
  4575. begin
  4576. LinesScroll:=-1;
  4577. cursorInVisibleArea:= (CurPos.Y>=Delta.Y) and (CurPos.Y<(Delta.Y+Size.Y)); {ignore folds here}
  4578. NL:=NextVisibleLine(CurPos.Y-1,false);
  4579. ScrollTo(Delta.X, Delta.Y + LinesScroll);
  4580. if cursorInVisibleArea and (CurPos.Y>=(Delta.Y+Size.Y)) then {do not allow corsor leave visible area}
  4581. if NL<>-1 then
  4582. SetCurPtr(CurPos.X,NL); {cursor stick to window bottom line}
  4583. end;
  4584. procedure TCustomCodeEditor.ScrollOneDown;
  4585. var NL: sw_integer;
  4586. LinesScroll : sw_integer;
  4587. cursorInVisibleArea : boolean;
  4588. begin
  4589. LinesScroll:=1;
  4590. cursorInVisibleArea:= (CurPos.Y>=Delta.Y) and (CurPos.Y<(Delta.Y+Size.Y)); {ignore folds here}
  4591. NL:=NextVisibleLine(CurPos.Y+1,true);
  4592. ScrollTo(Delta.X, Delta.Y + LinesScroll);
  4593. if cursorInVisibleArea and (CurPos.Y<Delta.Y) then {do not allow corsor leave visible area}
  4594. if NL>=0 then
  4595. SetCurPtr(CurPos.X,Min(GetLineCount-1,NL)); {cursor stick to window top line}
  4596. end;
  4597. procedure TCustomCodeEditor.TextStart;
  4598. begin
  4599. SetCurPtr(0,0);
  4600. end;
  4601. procedure TCustomCodeEditor.TextEnd;
  4602. var s : sw_astring;
  4603. i : longint;
  4604. begin
  4605. s:=GetDisplayText(GetLineCount-1);
  4606. i:=length(s);
  4607. while (i>0) and (s[i]=' ') do
  4608. dec(i);
  4609. i:=Min(i,MaxLineLength);
  4610. SetCurPtr(i,GetLineCount-1);
  4611. end;
  4612. procedure TCustomCodeEditor.WindowStart;
  4613. begin
  4614. if not NoSelect and ShouldExtend then
  4615. TextStart {select to start}
  4616. else
  4617. SetCurPtr(CurPos.X,Delta.Y);
  4618. end;
  4619. procedure TCustomCodeEditor.WindowEnd;
  4620. begin
  4621. if not NoSelect and ShouldExtend then
  4622. TextEnd {select to end}
  4623. else
  4624. SetCurPtr(CurPos.X,Delta.Y+Size.Y-1);
  4625. end;
  4626. procedure TCustomCodeEditor.JumpSelStart;
  4627. begin
  4628. if ValidBlock then
  4629. SetCurPtr(SelStart.X,SelStart.Y);
  4630. end;
  4631. procedure TCustomCodeEditor.JumpSelEnd;
  4632. begin
  4633. if ValidBlock then
  4634. SetCurPtr(SelEnd.X,SelEnd.Y);
  4635. end;
  4636. function TCustomCodeEditor.GetBookmark(MarkIdx: sw_integer):TEditorBookMark;
  4637. var LineNr : sw_integer;
  4638. begin
  4639. GetBookmark.Valid:=false;
  4640. if not (MarkIdx in [0..9]) then exit;
  4641. with Bookmarks[MarkIdx] do
  4642. if Valid=true then
  4643. begin
  4644. LineNr:=FindMarkLineNr(MarkIdx);
  4645. if LineNr>=0 then
  4646. Pos.Y:=LineNr
  4647. else
  4648. Valid:=false;
  4649. end;
  4650. GetBookmark:=Bookmarks[MarkIdx];
  4651. end;
  4652. procedure TCustomCodeEditor.SetBookmark(MarkIdx: sw_integer; ABookmark: TEditorBookMark);
  4653. var Line : PCustomLine;
  4654. begin
  4655. if not (MarkIdx in [0..9]) then exit;
  4656. Bookmarks[MarkIdx]:=ABookmark;
  4657. if ABookmark.Valid then
  4658. begin
  4659. {invalid Pos.Y will lead to crash check it beforehand }
  4660. if (ABookmark.Pos.X<0) or (ABookmark.Pos.X>MaxLineLength)
  4661. or (ABookmark.Pos.Y<0) or (ABookmark.Pos.Y>=GetLineCount) then
  4662. begin
  4663. Bookmarks[MarkIdx].Valid:=false;
  4664. exit;
  4665. end;
  4666. Line:=GetLine(ABookmark.Pos.Y);
  4667. if Assigned(Line) then
  4668. Line^.InsertMark(@Self,@Bookmarks[MarkIdx])
  4669. else
  4670. Bookmarks[MarkIdx].Valid:=false; {this should not be ever reached, but safety first}
  4671. end;
  4672. end;
  4673. function TCustomCodeEditor.FindMarkLineNr(MarkIdx: sw_integer):sw_integer;
  4674. var Count, CurLineNr, CurMarkNr : sw_integer;
  4675. Line : PCustomLine;
  4676. LI : PEditorLineInfo;
  4677. begin
  4678. Count:=GetLineCount;
  4679. FindMarkLineNr:=-1;
  4680. if Count>1 then
  4681. for CurLineNr:=0 to Count-1 do
  4682. begin
  4683. Line:=GetLine(CurLineNr);
  4684. if Assigned(Line) then LI:=Line^.GetEditorInfo(@Self) else LI:=nil;
  4685. if Assigned(LI) then
  4686. if Assigned(LI^.BookMarks) then
  4687. begin
  4688. CurMarkNr := LI^.BookMarks^.IndexOf(@Bookmarks[MarkIdx]);
  4689. if CurMarkNr>=0 then
  4690. begin
  4691. FindMarkLineNr:=CurLineNr;
  4692. break;
  4693. end;
  4694. end;
  4695. end;
  4696. end;
  4697. procedure TCustomCodeEditor.JumpMark(MarkIdx: integer);
  4698. var LineNr : sw_integer;
  4699. begin
  4700. if (MarkIdx<Low(Bookmarks)) or (MarkIdx>High(Bookmarks)) then
  4701. begin ErrorBox(FormatStrInt(msg_invalidmarkindex,MarkIdx),nil); Exit; end;
  4702. with Bookmarks[MarkIdx] do
  4703. if Valid=false then
  4704. InformationBox(FormatStrInt(msg_marknotset,MarkIdx),nil)
  4705. else
  4706. begin
  4707. DontConsiderShiftState:=true;
  4708. LineNr:=FindMarkLineNr(MarkIdx); {Find current marked line}
  4709. if LineNr>=0 then
  4710. SetCurPtr(Pos.X,LineNr)
  4711. else
  4712. InformationBox(FormatStrInt(msg_marknotset,MarkIdx),nil);
  4713. DontConsiderShiftState:=false;
  4714. end;
  4715. end;
  4716. procedure TCustomCodeEditor.DefineMark(MarkIdx: integer);
  4717. var Line : PCustomLine;
  4718. LI : PEditorLineInfo;
  4719. LineNr : sw_integer;
  4720. begin
  4721. if (MarkIdx<Low(Bookmarks)) or (MarkIdx>High(Bookmarks)) then
  4722. begin
  4723. ErrorBox(FormatStrInt(msg_invalidmarkindex,MarkIdx),nil);
  4724. Exit;
  4725. end;
  4726. if Bookmarks[MarkIdx].Valid then
  4727. begin
  4728. LineNr:=FindMarkLineNr(MarkIdx); {find current marked line}
  4729. if LineNr>=0 then
  4730. begin
  4731. Line:=GetLine(LineNr);
  4732. Line^.DeleteMark(@Self,@Bookmarks[MarkIdx]);
  4733. end;
  4734. end;
  4735. Line:=GetLine(CurPos.Y);
  4736. Line^.InsertMark(@Self,@Bookmarks[MarkIdx]);
  4737. with Bookmarks[MarkIdx] do
  4738. begin
  4739. Pos:=CurPos;
  4740. Valid:=true;
  4741. end;
  4742. end;
  4743. procedure TCustomCodeEditor.JumpToLastCursorPos;
  4744. begin
  4745. NotImplemented;
  4746. end;
  4747. procedure TCustomCodeEditor.UpperCase;
  4748. var StartP,EndP: TPoint;
  4749. begin
  4750. if ValidBlock=false then Exit;
  4751. GetSelectionArea(StartP,EndP);
  4752. AddGroupedAction(eaUpperCase);
  4753. ChangeCaseArea(StartP,EndP,caToUpperCase);
  4754. CloseGroupedAction(eaUpperCase);
  4755. end;
  4756. procedure TCustomCodeEditor.LowerCase;
  4757. var StartP,EndP: TPoint;
  4758. begin
  4759. if ValidBlock=false then Exit;
  4760. GetSelectionArea(StartP,EndP);
  4761. AddGroupedAction(eaLowerCase);
  4762. ChangeCaseArea(StartP,EndP,caToLowerCase);
  4763. CloseGroupedAction(eaLowerCase);
  4764. end;
  4765. procedure TCustomCodeEditor.ToggleCase;
  4766. var StartP,EndP: TPoint;
  4767. begin
  4768. if ValidBlock=false then Exit;
  4769. GetSelectionArea(StartP,EndP);
  4770. AddGroupedAction(eaToggleCase);
  4771. ChangeCaseArea(StartP,EndP,caToggleCase);
  4772. CloseGroupedAction(eaToggleCase);
  4773. end;
  4774. procedure TCustomCodeEditor.WordLowerCase;
  4775. var StartP,EndP: TPoint;
  4776. begin
  4777. if GetCurrentWordArea(StartP,EndP)=false then Exit;
  4778. AddGroupedAction(eaLowerCase);
  4779. ChangeCaseArea(StartP,EndP,caToLowerCase);
  4780. CloseGroupedAction(eaLowerCase);
  4781. end;
  4782. procedure TCustomCodeEditor.WordUpperCase;
  4783. var StartP,EndP: TPoint;
  4784. begin
  4785. if GetCurrentWordArea(StartP,EndP)=false then Exit;
  4786. AddGroupedAction(eaUpperCase);
  4787. ChangeCaseArea(StartP,EndP,caToUpperCase);
  4788. CloseGroupedAction(eaUpperCase);
  4789. end;
  4790. procedure TCustomCodeEditor.CreateFoldFromBlock;
  4791. var StartY,EndY: sw_integer;
  4792. begin
  4793. if not IsFlagSet(efFolds) then Exit;
  4794. if not ValidBlock then Exit;
  4795. StartY:=SelStart.Y; EndY:=SelEnd.Y;
  4796. if SelEnd.X=0 then Dec(EndY);
  4797. if CreateFold(StartY,EndY,false)=false then
  4798. ErrorBox(msg_foldboundsarenotvalid,nil);
  4799. end;
  4800. procedure TCustomCodeEditor.ToggleFold;
  4801. var F: PFold;
  4802. begin
  4803. if not IsFlagSet(efFolds) then Exit;
  4804. F:=GetLineFold(CurPos.Y);
  4805. if Assigned(F) then
  4806. F^.Collapse(not F^.Collapsed_);
  4807. end;
  4808. procedure TCustomCodeEditor.ExpandFold;
  4809. var F: PFold;
  4810. begin
  4811. if not IsFlagSet(efFolds) then Exit;
  4812. F:=GetLineFold(CurPos.Y);
  4813. if Assigned(F) then
  4814. F^.Collapse(false);
  4815. end;
  4816. procedure TCustomCodeEditor.CollapseFold;
  4817. var F: PFold;
  4818. begin
  4819. if not IsFlagSet(efFolds) then Exit;
  4820. F:=GetLineFold(CurPos.Y);
  4821. if Assigned(F) then
  4822. F^.Collapse(true);
  4823. end;
  4824. procedure TCustomCodeEditor.ChangeCaseArea(StartP,EndP: TPoint; CaseAction: TCaseAction);
  4825. var Y,X: sw_integer;
  4826. X1,X2: sw_integer;
  4827. S: sw_astring;
  4828. C: AnsiChar;
  4829. StartPos : TPoint;
  4830. HoldUndo : boolean;
  4831. begin
  4832. Lock;
  4833. HoldUndo:=GetStoreUndo;
  4834. SetStoreUndo(false);
  4835. for Y:=StartP.Y to EndP.Y do
  4836. begin
  4837. S:=GetDisplayText(Y);
  4838. { Pierre, please implement undo here! Gabor }
  4839. X1:=0; X2:=length(S)-1;
  4840. if Y=StartP.Y then X1:=StartP.X;
  4841. if Y=EndP.Y then X2:=EndP.X;
  4842. SetStoreUndo(HoldUndo);
  4843. StartPos.X:=X1;
  4844. StartPos.Y:=Y;
  4845. { the only drawback is that we keep
  4846. the original text even if Toggle where
  4847. it is not really necessary PM }
  4848. Addaction(eaOverwriteText,StartPos,StartPos,Copy(S,X1+1,X2-X1+1),GetFlags);
  4849. SetStoreUndo(false);
  4850. for X:=X1 to X2 do
  4851. begin
  4852. C:=S[X+1];
  4853. case CaseAction of
  4854. caToLowerCase : C:=LowCase(C);
  4855. caToUpperCase : C:=UpCase(C);
  4856. caToggleCase : if C in['a'..'z'] then
  4857. C:=Upcase(C)
  4858. else
  4859. C:=LowCase(C);
  4860. end;
  4861. S[X+1]:=C;
  4862. end;
  4863. SetDisplayText(Y,S);
  4864. end;
  4865. UpdateAttrsRange(StartP.Y,EndP.Y,attrAll);
  4866. DrawLines(CurPos.Y);
  4867. SetModified(true);
  4868. Addaction(eaMoveCursor,StartPos,CurPos,'',GetFlags);
  4869. SetStoreUndo(HoldUndo);
  4870. UnLock;
  4871. end;
  4872. procedure TCustomCodeEditor.PushInfo(Const st : string);
  4873. begin
  4874. { Dummies }
  4875. end;
  4876. procedure TCustomCodeEditor.PopInfo;
  4877. begin
  4878. { Dummies }
  4879. end;
  4880. procedure TCustomCodeEditor.InsertOptions;
  4881. begin
  4882. { Abstract }
  4883. NotImplemented;
  4884. end;
  4885. function TCustomCodeEditor.GetLineFold(EditorLine: sw_integer): PFold;
  4886. var L: PCustomLine;
  4887. LI: PEditorLineInfo;
  4888. F: PFold;
  4889. begin
  4890. F:=nil;
  4891. if IsFlagSet(efFolds) then
  4892. if (0<=EditorLine) and (EditorLine<GetLineCount) then
  4893. begin
  4894. L:=GetLine(EditorLine);
  4895. if Assigned(L) then
  4896. LI:=L^.GetEditorInfo(@Self)
  4897. else
  4898. LI:=nil;
  4899. if Assigned(LI) then
  4900. F:=LI^.Fold;
  4901. end;
  4902. GetLineFold:=F;
  4903. end;
  4904. function TCustomCodeEditor.IsLineVisible(EditorLine: sw_integer): boolean;
  4905. var V: boolean;
  4906. F,PrevF: PFold;
  4907. FoldHeadline: boolean;
  4908. begin
  4909. V:=true;
  4910. if IsFlagSet(efFolds) then
  4911. begin
  4912. F:=GetLineFold(EditorLine);
  4913. if Assigned(F) then
  4914. begin
  4915. PrevF:=GetLineFold(EditorLine-1);
  4916. FoldHeadline:=false;
  4917. if (PrevF<>F) and ((PrevF=nil) or (not PrevF^.IsParent(F))) then
  4918. FoldHeadline:=true;
  4919. if FoldHeadline then
  4920. begin
  4921. if Assigned(F^.ParentFold) and (F^.ParentFold^.IsCollapsed) then
  4922. V:=false;
  4923. end
  4924. else
  4925. if F^.IsCollapsed then
  4926. V:=false;
  4927. end;
  4928. end;
  4929. IsLineVisible:=V;
  4930. end;
  4931. function TCustomCodeEditor.ViewToEditorLine(ViewLine: sw_integer): sw_integer;
  4932. var I,Line,Count: sw_integer;
  4933. begin
  4934. if not IsFlagSet(efFolds) then
  4935. Line:=ViewLine
  4936. else
  4937. begin
  4938. Count:=GetLineCount;
  4939. I:=0; Line:=-1;
  4940. while (Line<ViewLine) and (I<Count) do
  4941. begin
  4942. if IsLineVisible(I) then
  4943. Inc(Line);
  4944. Inc(I);
  4945. end;
  4946. if Line<>ViewLine then
  4947. Line:=-1
  4948. else
  4949. Line:=I-1;
  4950. end;
  4951. ViewToEditorLine:=Line;
  4952. end;
  4953. function TCustomCodeEditor.EditorToViewLine(EditorLine: sw_integer): sw_integer;
  4954. var I,Line: sw_integer;
  4955. begin
  4956. if not IsFlagSet(efFolds) then
  4957. Line:=EditorLine
  4958. else
  4959. begin
  4960. Line:=-1;
  4961. for I:=0 to EditorLine do
  4962. if IsLineVisible(I) then
  4963. Inc(Line);
  4964. end;
  4965. EditorToViewLine:=Line;
  4966. end;
  4967. procedure TCustomCodeEditor.ViewToEditorPoint(P: TPoint; var NP: TPoint);
  4968. begin
  4969. NP.X:=P.X-GetReservedColCount;
  4970. NP.Y:=ViewToEditorLine(P.Y);
  4971. end;
  4972. procedure TCustomCodeEditor.EditorToViewPoint(P: TPoint; var NP: TPoint);
  4973. begin
  4974. NP.X:=P.X+GetReservedColCount;
  4975. NP.Y:=EditorToViewLine(P.Y);
  4976. end;
  4977. procedure TCustomCodeEditor.FindMatchingDelimiter(ScanForward: boolean);
  4978. const OpenSymbols : string[6] = '[{(<''"';
  4979. CloseSymbols : string[6] = ']})>''"';
  4980. var SymIdx: integer;
  4981. LineText,LineAttr: sw_astring;
  4982. CurChar: AnsiChar;
  4983. X,Y: sw_integer;
  4984. LineCount: sw_integer;
  4985. JumpPos: TPoint;
  4986. BracketLevel: integer;
  4987. begin
  4988. JumpPos.X:=-1; JumpPos.Y:=-1;
  4989. LineText:=GetDisplayText(CurPos.Y);
  4990. LineText:=copy(LineText,CurPos.X+1,1);
  4991. if LineText='' then Exit;
  4992. CurChar:=LineText[1];
  4993. Y:=CurPos.Y; X:=CurPos.X; LineCount:=0;
  4994. BracketLevel:=1;
  4995. if ScanForward then
  4996. begin
  4997. SymIdx:=Pos(CurChar,OpenSymbols);
  4998. if SymIdx=0 then Exit;
  4999. repeat
  5000. Inc(LineCount);
  5001. GetDisplayTextFormat(Y,LineText,LineAttr);
  5002. if LineCount<>1 then X:=-1;
  5003. repeat
  5004. Inc(X);
  5005. if X<length(LineText) then
  5006. if copy(LineAttr,X+1,1)<>chr(attrComment) then
  5007. if (LineText[X+1]=CloseSymbols[SymIdx]) and (BracketLevel=1) then
  5008. begin
  5009. JumpPos.X:=X; JumpPos.Y:=Y;
  5010. end
  5011. else
  5012. if LineText[X+1]=OpenSymbols[SymIdx] then
  5013. Inc(BracketLevel)
  5014. else
  5015. if LineText[X+1]=CloseSymbols[SymIdx] then
  5016. if BracketLevel>1 then
  5017. Dec(BracketLevel);
  5018. until (X>=length(LineText)) or (JumpPos.X<>-1);
  5019. Inc(Y);
  5020. until (Y>=GetLineCount) or (JumpPos.X<>-1);
  5021. end
  5022. else
  5023. begin
  5024. SymIdx:=Pos(CurChar,CloseSymbols);
  5025. if SymIdx=0 then Exit;
  5026. repeat
  5027. Inc(LineCount);
  5028. GetDisplayTextFormat(Y,LineText,LineAttr);
  5029. if LineCount<>1 then X:=length(LineText);
  5030. repeat
  5031. Dec(X);
  5032. if X>0 then
  5033. if copy(LineAttr,X+1,1)<>chr(attrComment) then
  5034. if (LineText[X+1]=OpenSymbols[SymIdx]) and (BracketLevel=1) then
  5035. begin
  5036. JumpPos.X:=X; JumpPos.Y:=Y;
  5037. end
  5038. else
  5039. if LineText[X+1]=CloseSymbols[SymIdx] then
  5040. Inc(BracketLevel)
  5041. else
  5042. if LineText[X+1]=OpenSymbols[SymIdx] then
  5043. if BracketLevel>1 then
  5044. Dec(BracketLevel);
  5045. until (X<0) or (JumpPos.X<>-1);
  5046. Dec(Y);
  5047. until (Y<0) or (JumpPos.X<>-1);
  5048. end;
  5049. if JumpPos.X<>-1 then
  5050. begin
  5051. SetCurPtr(JumpPos.X,JumpPos.Y);
  5052. TrackCursor(do_centre);
  5053. end;
  5054. end;
  5055. function TCustomCodeEditor.InsertNewLine: Sw_integer;
  5056. var i,Ind: Sw_integer;
  5057. S,IndentStr: Sw_astring;
  5058. procedure CalcIndent(LineOver: Sw_integer);
  5059. begin
  5060. if (LineOver<0) or (LineOver>GetLineCount) or ((GetFlags and efNoIndent)<>0) then
  5061. Ind:=0 else
  5062. begin
  5063. repeat
  5064. IndentStr:=GetDisplayText(LineOver);
  5065. Dec(LineOver);
  5066. until (LineOver<0) or (IndentStr<>'');
  5067. Ind:=0;
  5068. while (Ind<length(IndentStr)) and (IndentStr[Ind+1]=' ') do
  5069. Inc(Ind);
  5070. end;
  5071. IndentStr:=CharStr(' ',Ind);
  5072. end;
  5073. var {SelBack: sw_integer;}
  5074. SCP: TPoint;
  5075. CI : sw_integer;
  5076. HoldUndo : Boolean;
  5077. L,NewL: PCustomLine;
  5078. EI,NewEI: PEditorLineInfo;
  5079. begin
  5080. if IsReadOnly then begin InsertNewLine:=-1; Exit; end;
  5081. Lock;
  5082. SCP:=CurPos;
  5083. HoldUndo:=GetStoreUndo;
  5084. SetStoreUndo(false);
  5085. if CurPos.Y<GetLineCount then S:=GetLineText(CurPos.Y) else S:='';
  5086. if Overwrite=false then
  5087. begin
  5088. if CurPos.Y<GetLineCount then
  5089. begin
  5090. L:=GetLine(CurPos.Y);
  5091. if not assigned(L) then
  5092. EI:=nil
  5093. else
  5094. EI:=L^.GetEditorInfo(@Self);
  5095. end
  5096. else
  5097. EI:=nil;
  5098. { SelBack:=0;}
  5099. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  5100. if GetLineCount>0 then
  5101. begin
  5102. S:=GetLineText(CurPos.Y);
  5103. { SelBack:=length(S)-SelEnd.X;}
  5104. SetLineText(CurPos.Y,RTrim(S,not IsFlagSet(efUseTabCharacters)));
  5105. end;
  5106. CalcIndent(CurPos.Y);
  5107. SetLineText(CurPos.Y,copy(S,1,CI-1));
  5108. S:=copy(S,CI,Length(S));
  5109. i:=1;
  5110. while (i<=length(s)) and (i<=length(IndentStr)) and (s[i]=' ') do
  5111. inc(i);
  5112. if i>1 then
  5113. Delete(IndentStr,1,i-1);
  5114. NewL:=InsertLine(CurPos.Y+1,IndentStr+S);
  5115. LimitsChanged;
  5116. (* if PointOfs(SelStart)<>PointOfs(SelEnd) then { !!! check it - it's buggy !!! }
  5117. begin SelEnd.Y:=CurPos.Y+1; SelEnd.X:=length(GetLineText(CurPos.Y+1))-SelBack; end;*)
  5118. UpdateAttrs(CurPos.Y,attrAll);
  5119. AdjustBookMark(CurPos.X,Ind,CurPos.Y,CurPos.Y+1);
  5120. SetCurPtr(Ind,CurPos.Y+1);
  5121. NewEI:=NewL^.GetEditorInfo(@Self);
  5122. if Assigned(EI) and Assigned(NewEI) then
  5123. begin
  5124. NewEI^.SetFold(EI^.Fold);
  5125. if Assigned(EI^.Fold) then
  5126. if EI^.Fold^.IsCollapsed then
  5127. EI^.Fold^.Collapse(false);
  5128. end;
  5129. SetStoreUndo(HoldUndo);
  5130. { obsolete IndentStr is taken care of by the Flags PM }
  5131. Addaction(eaInsertLine,SCP,CurPos,CharStr(' ',i-1){IndentStr},GetFlags);
  5132. SetStoreUndo(false);
  5133. AdjustSelectionPos(SCP.X,SCP.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
  5134. end else
  5135. begin
  5136. CalcIndent(CurPos.Y);
  5137. if CurPos.Y=GetLineCount-1 then
  5138. begin
  5139. AddLine(IndentStr);
  5140. AdjustSelectionBefore(0,1);
  5141. LimitsChanged;
  5142. SetStoreUndo(HoldUndo);
  5143. UpdateAttrs(CurPos.Y,attrAll);
  5144. AdjustBookMark(CurPos.X,Ind,CurPos.Y,CurPos.Y+1);
  5145. SetCurPtr(Ind,CurPos.Y+1);
  5146. { obsolete IndentStr is taken care of by the Flags PM }
  5147. Addaction(eaInsertLine,SCP,CurPos,''{IndentStr},GetFlags);
  5148. SetStoreUndo(false);
  5149. end
  5150. else
  5151. begin
  5152. UpdateAttrs(CurPos.Y,attrAll);
  5153. SetStoreUndo(HoldUndo);
  5154. AdjustBookMark(CurPos.X,Ind,CurPos.Y,CurPos.Y+1);
  5155. SetCurPtr(Ind,CurPos.Y+1);
  5156. AddAction(eaMoveCursor,SCP,CurPos,'',GetFlags);
  5157. SetStoreUndo(false);
  5158. end;
  5159. end;
  5160. DrawLines(CurPos.Y);
  5161. SetStoreUndo(HoldUndo);
  5162. SetModified(true);
  5163. Unlock;
  5164. end;
  5165. procedure TCustomCodeEditor.BreakLine;
  5166. var
  5167. SCP: TPoint;
  5168. begin
  5169. { Like insert new line, but leave current pos unchanged }
  5170. SCP:=CurPos;
  5171. InsertNewLine;
  5172. SetCurPtr(SCP.X,SCP.Y);
  5173. end;
  5174. procedure TCustomCodeEditor.BackSpace;
  5175. var S,PreS: sw_astring;
  5176. OI,CI,CP,Y,TX: Sw_integer;
  5177. SCP,SC1 : TPoint;
  5178. HoldUndo : Boolean;
  5179. begin
  5180. if IsReadOnly then Exit;
  5181. Lock;
  5182. SCP:=CurPos;
  5183. HoldUndo:=GetStoreUndo;
  5184. SetStoreUndo(false);
  5185. if CurPos.X=0 then
  5186. begin
  5187. if CurPos.Y>0 then
  5188. begin
  5189. CI:=Length(GetDisplayText(CurPos.Y-1));
  5190. AdjustBookMark(0,CI,CurPos.Y,CurPos.Y-1);
  5191. S:=GetLineText(CurPos.Y-1);
  5192. SetLineText(CurPos.Y-1,S+GetLineText(CurPos.Y));
  5193. SC1.X:=Length(S);SC1.Y:=CurPOS.Y-1;
  5194. SetStoreUndo(HoldUndo);
  5195. AddAction(eaDeleteLine,SCP,SC1,GetLineText(CurPos.Y),GetFlags);
  5196. SetStoreUndo(false);
  5197. DeleteLine(CurPos.Y);
  5198. LimitsChanged;
  5199. SetCurPtr(CI,CurPos.Y-1);
  5200. AdjustSelectionPos(Ci,CurPos.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
  5201. end;
  5202. end
  5203. else
  5204. begin
  5205. CP:=CurPos.X-1;
  5206. S:=GetLineText(CurPos.Y);
  5207. CI:=LinePosToCharIdx(CurPos.Y,CP);
  5208. if (ci>0) and (ci<=length(S)) then
  5209. if (s[ci]=TAB) {and (CharIdxToLinePos(Curpos.y,ci)=cp)} then
  5210. CP:=CharIdxToLinePos(CurPos.Y,CI);
  5211. if IsFlagSet(efBackspaceUnindents) then
  5212. begin
  5213. S:=GetDisplayText(CurPos.Y);
  5214. if Trim(copy(S,1,CP+1))='' then
  5215. begin
  5216. Y:=CurPos.Y;
  5217. while (Y>0) do
  5218. begin
  5219. Dec(Y);
  5220. PreS:=GetDisplayText(Y);
  5221. if Trim(copy(PreS,1,CP+1))<>'' then Break;
  5222. end;
  5223. if Y<0 then PreS:='';
  5224. TX:=0;
  5225. while (TX<length(PreS)) and (PreS[TX+1]=' ') do
  5226. Inc(TX);
  5227. if TX<CP then CP:=TX;
  5228. end;
  5229. end;
  5230. S:=GetLineText(CurPos.Y);
  5231. OI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  5232. CI:=LinePosToCharIdx(CurPos.Y,CP);
  5233. SetLineText(CurPos.Y,copy(S,1,CI-1)+copy(S,OI,Length(S)));
  5234. SetCurPtr(CP,CurPos.Y);
  5235. SetStoreUndo(HoldUndo);
  5236. Addaction(eaDeleteText,SCP,CurPos,Copy(S,CI,OI-CI),GetFlags);
  5237. SetStoreUndo(false);
  5238. AdjustSelectionPos(SCP.X-1,SCP.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
  5239. end;
  5240. UpdateAttrs(CurPos.Y,attrAll);
  5241. DrawLines(CurPos.Y);
  5242. SetStoreUndo(HoldUndo);
  5243. SetModified(true);
  5244. Unlock;
  5245. end;
  5246. procedure TCustomCodeEditor.DelChar;
  5247. var S: sw_astring;
  5248. SDX,SDY,CI : sw_integer;
  5249. HoldUndo : boolean;
  5250. SCP : TPoint;
  5251. begin
  5252. if IsReadOnly then Exit;
  5253. Lock;
  5254. HoldUndo:=GetStoreUndo;
  5255. SetStoreUndo(false);
  5256. S:=GetLineText(CurPos.Y);
  5257. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  5258. if (CI>length(S)) or (S='') then
  5259. begin
  5260. if CurPos.Y<GetLineCount-1 then
  5261. begin
  5262. SetLineText(CurPos.Y,S+CharStr(' ',CurPOS.X-Length(S))+GetLineText(CurPos.Y+1));
  5263. AdjustBookMark(0,CurPos.X,CurPos.Y+1,CurPos.Y);
  5264. SDX:=CurPos.X;
  5265. SetStoreUndo(HoldUndo);
  5266. SCP.X:=0;SCP.Y:=CurPos.Y+1;
  5267. AddGroupedAction(eaDelChar);
  5268. AddAction(eaMoveCursor,CurPos,SCP,'',GetFlags);
  5269. S:=GetLineText(CurPos.Y+1);
  5270. AddAction(eaDeleteLine,SCP,CurPos,S,GetFlags);
  5271. CloseGroupedAction(eaDelChar);
  5272. SetStoreUndo(false);
  5273. DeleteLine(CurPos.Y+1);
  5274. LimitsChanged;
  5275. SDY:=-1;
  5276. SetCurPtr(CurPos.X,CurPos.Y);
  5277. UpdateAttrs(CurPos.Y,attrAll);
  5278. AdjustSelectionPos(CurPos.X,CurPos.Y,SDX,SDY);
  5279. end;
  5280. end
  5281. else
  5282. begin
  5283. SCP:=CurPos;
  5284. { Problem if S[CurPos.X+1]=TAB !! PM }
  5285. if S[CI]=TAB then
  5286. begin
  5287. { we want to remove the tab if we are at the first place
  5288. of the tab, but the following test was true for the last position
  5289. in tab
  5290. if CharIdxToLinePos(Curpos.y,ci)=Curpos.x then }
  5291. if CharIdxToLinePos(Curpos.y,ci-1)=Curpos.x-1 then
  5292. Delete(S,Ci,1)
  5293. else
  5294. S:=Copy(S,1,CI-1)+CharStr(' ',GetTabSize-1)+Copy(S,CI+1,Length(S));
  5295. SetStoreUndo(HoldUndo);
  5296. Addaction(eaDeleteText,CurPos,CurPos,#9,GetFlags);
  5297. SDX:=-1;
  5298. SetStoreUndo(false);
  5299. end
  5300. else
  5301. begin
  5302. SetStoreUndo(HoldUndo);
  5303. Addaction(eaDeleteText,CurPos,CurPos,S[CI],GetFlags);
  5304. SetStoreUndo(false);
  5305. SDX:=-1;
  5306. Delete(S,CI,1);
  5307. end;
  5308. SetLineText(CurPos.Y,S);
  5309. SDY:=0;
  5310. SetCurPtr(CurPos.X,CurPos.Y);
  5311. UpdateAttrs(CurPos.Y,attrAll);
  5312. AdjustSelectionPos(SCP.X,SCP.Y,SDX,SDY);
  5313. end;
  5314. DrawLines(CurPos.Y);
  5315. SetStoreUndo(HoldUndo);
  5316. SetModified(true);
  5317. Unlock;
  5318. end;
  5319. procedure TCustomCodeEditor.DelWord;
  5320. var
  5321. SP,EP : TPoint;
  5322. SelSize : sw_integer;
  5323. begin
  5324. if IsReadOnly then Exit;
  5325. Lock;
  5326. SP:=SelStart;
  5327. EP:=SelEnd;
  5328. SetSelection(SelStart,SelStart);
  5329. SelectWord;
  5330. SelSize:=SelEnd.X-SelStart.X;
  5331. DelSelect;
  5332. SetSelection(SP,EP);
  5333. AdjustSelectionPos(CurPos.X,CurPos.Y,-SelSize,0);
  5334. if SelSize>0 then
  5335. SetModified(true);
  5336. Unlock;
  5337. end;
  5338. procedure TCustomCodeEditor.DelToEndOfWord;
  5339. var
  5340. SP,EP : TPoint;
  5341. S : String;
  5342. SelSize : sw_integer;
  5343. begin
  5344. if IsReadOnly then Exit;
  5345. Lock;
  5346. SP:=SelStart;
  5347. EP:=SelEnd;
  5348. SetSelection(SelStart,SelStart);
  5349. SelectWord;
  5350. S:=GetDisplayText(CurPos.Y);
  5351. if ((SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y)) then
  5352. begin
  5353. if (Length(S) <= CurPos.X) then
  5354. begin
  5355. SetSelection(SP,EP);
  5356. DelChar;
  5357. Unlock;
  5358. exit;
  5359. end
  5360. else
  5361. begin
  5362. SelEnd.X:=CurPos.X+1;
  5363. SelEnd.Y:=CurPos.Y;
  5364. end;
  5365. end;
  5366. while (length(S)>= SelEnd.X+1) and
  5367. ((S[SelEnd.X+1]=' ') or (S[SelEnd.X+1]=TAB)) do
  5368. inc(SelEnd.X);
  5369. SetSelection(CurPos,SelEnd);
  5370. SelSize:=SelEnd.X-SelStart.X;
  5371. DelSelect;
  5372. SetSelection(SP,EP);
  5373. AdjustSelectionPos(CurPos.X,CurPos.Y,-SelSize,0);
  5374. if SelSize>0 then
  5375. SetModified(true);
  5376. Unlock;
  5377. end;
  5378. procedure TCustomCodeEditor.DelStart;
  5379. var S: sw_astring;
  5380. OI: Sw_integer;
  5381. HoldUndo : Boolean;
  5382. SCP : TPoint;
  5383. begin
  5384. if IsReadOnly then Exit;
  5385. Lock;
  5386. HoldUndo:=GetStoreUndo;
  5387. SetStoreUndo(false);
  5388. SCP:=CurPos;
  5389. S:=GetLineText(CurPos.Y);
  5390. if (S<>'') and (CurPos.X<>0) then
  5391. begin
  5392. OI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  5393. SetLineText(CurPos.Y,copy(S,OI,Length(S)));
  5394. SetCurPtr(0,CurPos.Y);
  5395. SetStoreUndo(HoldUndo);
  5396. Addaction(eaDeleteText,SCP,CurPos,copy(S,1,OI-1),GetFlags);
  5397. SetStoreUndo(false);
  5398. AdjustSelectionPos(CurPos.X,CurPos.Y,-length(copy(S,1,OI-1)),0);
  5399. UpdateAttrs(CurPos.Y,attrAll);
  5400. DrawLines(CurPos.Y);
  5401. SetModified(true);
  5402. end;
  5403. SetStoreUndo(HoldUndo);
  5404. Unlock;
  5405. end;
  5406. procedure TCustomCodeEditor.DelEnd;
  5407. var S: sw_astring;
  5408. OI: Sw_integer;
  5409. HoldUndo : Boolean;
  5410. SCP : TPoint;
  5411. begin
  5412. if IsReadOnly then Exit;
  5413. Lock;
  5414. HoldUndo:=GetStoreUndo;
  5415. SetStoreUndo(false);
  5416. SCP:=CurPos;
  5417. S:=GetLineText(CurPos.Y);
  5418. if (S<>'') and (CurPos.X<>length(S)) then
  5419. begin
  5420. OI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  5421. SetLineText(CurPos.Y,copy(S,1,OI-1));
  5422. SetCurPtr(CurPos.X,CurPos.Y);
  5423. SetStoreUndo(HoldUndo);
  5424. Addaction(eaDeleteText,SCP,CurPos,copy(S,OI,Length(S)),GetFlags);
  5425. SetStoreUndo(false);
  5426. AdjustSelectionPos(CurPos.X+1,CurPos.Y,-length(copy(S,OI,Length(S)))+1,0);
  5427. UpdateAttrs(CurPos.Y,attrAll);
  5428. DrawLines(CurPos.Y);
  5429. SetModified(true);
  5430. end;
  5431. SetStoreUndo(HoldUndo);
  5432. Unlock;
  5433. end;
  5434. procedure TCustomCodeEditor.DelLine;
  5435. var
  5436. HoldUndo : boolean;
  5437. SP : TPoint;
  5438. S : Sw_AString;
  5439. begin
  5440. if IsReadOnly then Exit;
  5441. Lock;
  5442. if GetLineCount>0 then
  5443. begin
  5444. SP:=CurPos;
  5445. S:=GetLineText(CurPos.Y);
  5446. HoldUndo:=GetStoreUndo;
  5447. SetStoreUndo(false);
  5448. DeleteLine(CurPos.Y);
  5449. LimitsChanged;
  5450. AdjustSelectionBefore(0,-1);
  5451. SetCurPtr(0,CurPos.Y);
  5452. UpdateAttrs(Max(0,CurPos.Y-1),attrAll);
  5453. DrawLines(CurPos.Y);
  5454. SetStoreUndo(HoldUndo);
  5455. AddAction(eaDeleteLine,SP,CurPos,S,GetFlags);
  5456. SetModified(true);
  5457. end;
  5458. Unlock;
  5459. end;
  5460. procedure TCustomCodeEditor.InsMode;
  5461. begin
  5462. SetInsertMode(Overwrite);
  5463. end;
  5464. function TCustomCodeEditor.GetCurrentWordArea(var StartP,EndP: TPoint): boolean;
  5465. const WordChars = ['A'..'Z','a'..'z','0'..'9','_'];
  5466. var P : TPoint;
  5467. S : Sw_AString;
  5468. StartPos,EndPos : sw_integer;
  5469. OK: boolean;
  5470. begin
  5471. P:=CurPos;
  5472. S:=GetLineText(P.Y);
  5473. StartPos:=P.X+1;
  5474. EndPos:=StartPos;
  5475. Ok:=false;
  5476. if Length(S)>=StartPos then
  5477. OK:=(S[StartPos] in WordChars);
  5478. if OK then
  5479. begin
  5480. While (StartPos>1) and (S[StartPos-1] in WordChars) do
  5481. Dec(StartPos);
  5482. While (EndPos<Length(S)) and (S[EndPos+1] in WordChars) do
  5483. Inc(EndPos);
  5484. StartP.X:=StartPos-1; StartP.Y:=CurPos.Y;
  5485. EndP.X:=EndPos-1; EndP.Y:=CurPos.Y;
  5486. end;
  5487. GetCurrentWordArea:=OK;
  5488. end;
  5489. function TCustomCodeEditor.GetCurrentWord : string;
  5490. var S: sw_astring;
  5491. StartP,EndP: TPoint;
  5492. begin
  5493. if GetCurrentWordArea(StartP,EndP)=false then
  5494. S:=''
  5495. else
  5496. begin
  5497. S:=GetLineText(StartP.Y);
  5498. S:=copy(S,StartP.X+1,EndP.X-StartP.X+1);
  5499. end;
  5500. GetCurrentWord:=S; {Note: AnsiString to ShortString convertion}
  5501. end;
  5502. procedure TCustomCodeEditor.StartSelect;
  5503. var P1,P2: TPoint;
  5504. begin
  5505. if ValidBlock=false then
  5506. begin
  5507. { SetSelection(SelStart,Limit);}
  5508. P1:=CurPos; P2:=CurPos; {P2.X:=length(GetLineText(P2.Y))+1;}
  5509. SetSelection(P1,P2);
  5510. end
  5511. else
  5512. SetSelection(CurPos,SelEnd);
  5513. if PointOfs(SelEnd)<PointOfs(SelStart) then
  5514. SetSelection(SelStart,SelStart);
  5515. CheckSels;
  5516. DrawView;
  5517. end;
  5518. procedure TCustomCodeEditor.EndSelect;
  5519. var P: TPoint;
  5520. { LS: sw_integer;}
  5521. begin
  5522. P:=CurPos;
  5523. { don't try to jump to end of line, not for now
  5524. LS:=length(GetLineText(P.Y));
  5525. if LS<P.X then P.X:=LS; }
  5526. SetSelection(SelStart,P);
  5527. CheckSels;
  5528. DrawView;
  5529. end;
  5530. procedure TCustomCodeEditor.DelSelect;
  5531. var LineDelta, LineCount, CurLine: Sw_integer;
  5532. StartX,EndX,LastX: Sw_integer;
  5533. S,Z: sw_astring;
  5534. SPos : TPoint;
  5535. begin
  5536. if IsReadOnly or (ValidBlock=false) then Exit;
  5537. Lock;
  5538. AddGroupedAction(eaDelBlock);
  5539. LineCount:=(SelEnd.Y-SelStart.Y)+1;
  5540. LineDelta:=0; LastX:=CurPos.X;
  5541. CurLine:=SelStart.Y;
  5542. { single line : easy }
  5543. if LineCount=1 then
  5544. begin
  5545. S:=GetDisplayText(CurLine);
  5546. StartX:=SelStart.X;
  5547. EndX:=SelEnd.X;
  5548. SetDisplayText(CurLine,RExpand(copy(S,1,StartX),StartX)
  5549. +copy(S,EndX+1,Length(S)));
  5550. if GetStoreUndo then
  5551. begin
  5552. SPos.X:=StartX;
  5553. SPos.Y:=CurLine;
  5554. AddAction(eaDeleteText,SPos,SPos,Copy(S,StartX+1,EndX-StartX),GetFlags);
  5555. end;
  5556. Inc(CurLine);
  5557. LastX:=SelStart.X;
  5558. end
  5559. { several lines : a bit less easy }
  5560. else
  5561. begin
  5562. S:=GetDisplayText(CurLine);
  5563. StartX:=SelStart.X;
  5564. EndX:=SelEnd.X;
  5565. Z:=GetDisplayText(CurLine+LineCount-1);
  5566. SetDisplayText(CurLine,RExpand(copy(S,1,StartX),StartX)
  5567. +copy(Z,EndX+1,Length(Z)));
  5568. if GetStoreUndo then
  5569. begin
  5570. SPos.X:=StartX;
  5571. SPos.Y:=CurLine;
  5572. AddAction(eaDeleteText,SPos,SPos,Copy(S,StartX+1,Length(S)),GetFlags);
  5573. S:=GetDisplayText(CurLine+LineCount-1);
  5574. end;
  5575. Inc(CurLine);
  5576. Inc(LineDelta);
  5577. LastX:=SelStart.X;
  5578. while (LineDelta<LineCount) do
  5579. begin
  5580. { delete the complete line }
  5581. DeleteLine(CurLine);
  5582. Inc(LineDelta);
  5583. end;
  5584. if GetStoreUndo then
  5585. begin
  5586. AddAction(eaInsertText,SPos,SPos,Copy(S,EndX+1,Length(S)),GetFlags);
  5587. end;
  5588. end;
  5589. HideSelect;
  5590. SetCurPtr(LastX,CurLine-1);
  5591. UpdateAttrs(CurPos.Y,attrAll);
  5592. DrawLines(CurPos.Y);
  5593. SetModified(true);
  5594. CloseGroupedAction(eaDelBlock);
  5595. UnLock;
  5596. end;
  5597. procedure TCustomCodeEditor.HideSelect;
  5598. begin
  5599. SetSelection(CurPos,CurPos);
  5600. DrawLines(Delta.Y);
  5601. end;
  5602. procedure TCustomCodeEditor.CopyBlock;
  5603. var Temp: PCodeEditor;
  5604. R: TRect;
  5605. begin
  5606. if IsReadOnly or (ValidBlock=false) then Exit;
  5607. Lock;
  5608. GetExtent(R);
  5609. AddGroupedAction(eaCopyBlock);
  5610. New(Temp, Init(R, nil, nil, nil,nil));
  5611. Temp^.InsertFrom(@Self);
  5612. (* Temp^.SelectAll(true);
  5613. { this selects one line too much because
  5614. we have a empty line at creation to avoid
  5615. negative line problems so we need to decrease SelEnd.Y }
  5616. Dec(Temp^.SelEnd.Y);*)
  5617. InsertFrom(Temp);
  5618. Dispose(Temp, Done);
  5619. CloseGroupedAction(eaCopyBlock);
  5620. UnLock;
  5621. end;
  5622. procedure TCustomCodeEditor.MoveBlock;
  5623. var Temp: PCodeEditor;
  5624. R: TRect;
  5625. OldPos: TPoint;
  5626. begin
  5627. if IsReadOnly then Exit;
  5628. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  5629. Lock;
  5630. AddGroupedAction(eaMoveBlock);
  5631. GetExtent(R);
  5632. New(Temp, Init(R, nil, nil, nil,nil));
  5633. Temp^.InsertFrom(@Self);
  5634. OldPos:=CurPos;
  5635. if CurPos.Y>SelStart.Y then
  5636. Dec(OldPos.Y,Temp^.GetLineCount-1);
  5637. DelSelect;
  5638. SetCurPtr(OldPos.X,OldPos.Y);
  5639. InsertFrom(Temp);
  5640. Dispose(Temp, Done);
  5641. CloseGroupedAction(eaMoveBlock);
  5642. UnLock;
  5643. end;
  5644. procedure TCustomCodeEditor.IndentBlock;
  5645. var
  5646. ey,i,Indlen : Sw_Integer;
  5647. S,Ind : Sw_AString;
  5648. Pos : Tpoint;
  5649. {WasPersistentBlocks : boolean;}
  5650. begin
  5651. if IsReadOnly then Exit;
  5652. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  5653. Lock;
  5654. AddGroupedAction(eaIndentBlock);
  5655. { as SetCurPtr commented out, no need take care of Persistent Blocks
  5656. WasPersistentBlocks:=IsFlagSet(efPersistentBlocks);
  5657. if not WasPersistentBlocks then
  5658. SetFlags(GetFlags or efPersistentBlocks); }
  5659. ey:=selend.y;
  5660. if selend.x=0 then
  5661. dec(ey);
  5662. S:='';
  5663. { If AutoIndent try to align first line to
  5664. last line before selection }
  5665. { DISABLED created problems PM
  5666. if IsFlagSet(efAutoIndent) and (SelStart.Y>0) then
  5667. begin
  5668. i:=SelStart.Y-1;
  5669. while (S='') and (i>=0) do
  5670. begin
  5671. S:=GetDisplayText(i);
  5672. dec(i);
  5673. end;
  5674. if (S='') or (S[1]<>' ') then
  5675. Ind:=' '
  5676. else
  5677. begin
  5678. i:=1;
  5679. while (i<=Length(S)) and (S[i]=' ') do
  5680. inc(i);
  5681. indlen:=i;
  5682. S:=GetDisplayText(SelStart.Y);
  5683. i:=1;
  5684. while (i<=Length(S)) and (S[i]=' ') do
  5685. inc(i);
  5686. indlen:=indlen-i;
  5687. if indlen<=0 then
  5688. indlen:=1;
  5689. Ind:=CharStr(' ',indlen);
  5690. end;
  5691. end
  5692. else
  5693. Ind:=' ';}
  5694. Indlen:=GetIndentSize;
  5695. {selection Start and End move along}
  5696. if SelStart.X>0 then inc(SelStart.X,Indlen);
  5697. if SelEnd.X>0 then inc(SelEnd.X,Indlen);
  5698. Ind:=CharStr(' ',Indlen);
  5699. for i:=selstart.y to ey do
  5700. begin
  5701. S:=GetLineText(i);
  5702. SetLineText(i,Ind+S);
  5703. Pos.X:=0;Pos.Y:=i;
  5704. AddAction(eaInsertText,Pos,Pos,Ind,GetFlags);
  5705. end;
  5706. { this removes selection if Shift is pressed as well and we do not change cursor position anyway
  5707. SetCurPtr(CurPos.X,CurPos.Y); }
  5708. {after SetCurPtr return PersistentBlocks as it was before}
  5709. { as SetCurPtr commented out, no need take care of Persistent Blocks
  5710. if not WasPersistentBlocks then
  5711. SetFlags(GetFlags and (not longword(efPersistentBlocks))); }
  5712. { must be added manually here PM }
  5713. AddAction(eaMoveCursor,Pos,CurPos,'',GetFlags);
  5714. UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
  5715. DrawLines(CurPos.Y);
  5716. SetModified(true);
  5717. CloseGroupedAction(eaIndentBlock);
  5718. UnLock;
  5719. end;
  5720. procedure TCustomCodeEditor.UnindentBlock;
  5721. var
  5722. ey,i,j,k,indlen : Sw_integer;
  5723. S : Sw_AString;
  5724. Pos : TPoint;
  5725. {WasPersistentBlocks : boolean;}
  5726. begin
  5727. if IsReadOnly then Exit;
  5728. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  5729. Lock;
  5730. AddGroupedAction(eaUnindentBlock);
  5731. { as SetCurPtr commented out, no need take care of Persistent Blocks
  5732. WasPersistentBlocks:=IsFlagSet(efPersistentBlocks);
  5733. if not WasPersistentBlocks then
  5734. SetFlags(GetFlags or efPersistentBlocks);
  5735. }
  5736. ey:=selend.y;
  5737. if selend.x=0 then
  5738. dec(ey);
  5739. { If AutoIndent try to align first line to
  5740. last line before selection }
  5741. { Disabled created problems
  5742. if IsFlagSet(efAutoIndent) and (SelStart.Y>0) then
  5743. begin
  5744. S:=GetDisplayText(SelStart.Y);
  5745. i:=1;
  5746. while (i<=Length(S)) and (S[i]=' ') do
  5747. inc(i);
  5748. indlen:=i-1;
  5749. i:=SelStart.Y-1;
  5750. S:='';
  5751. while (S='') and (i>=0) do
  5752. begin
  5753. if Trim(Copy(GetDisplayText(i),1,indlen))='' then
  5754. S:=''
  5755. else
  5756. S:=GetDisplayText(i);
  5757. dec(i);
  5758. end;
  5759. if (S='') then
  5760. Indlen:=1
  5761. else
  5762. begin
  5763. i:=1;
  5764. while (i<=Length(S)) and (S[i]=' ') do
  5765. inc(i);
  5766. indlen:=indlen-i+1;
  5767. if indlen<=0 then
  5768. indlen:=1;
  5769. end;
  5770. end
  5771. else
  5772. Indlen:=1;}
  5773. Indlen:=GetIndentSize;
  5774. {selection Start and End move along}
  5775. if SelStart.X>0 then dec(SelStart.X,Indlen);
  5776. if SelStart.X<0 then SelStart.X:=0;
  5777. if SelEnd.X>0 then dec(SelEnd.X,Indlen);
  5778. if SelEnd.X<0 then begin SelEnd.X:=0; inc(SelEnd.Y); end;
  5779. {do indent line by line}
  5780. for i:=selstart.y to ey do
  5781. begin
  5782. S:=GetLineText(i);
  5783. k:=0;
  5784. for j:=1 to indlen do
  5785. if (length(s)>1) and (S[1]=' ') then
  5786. begin
  5787. Delete(s,1,1);
  5788. inc(k);
  5789. end;
  5790. SetLineText(i,S);
  5791. if k>0 then
  5792. begin
  5793. Pos.Y:=i;
  5794. Pos.X:=0;
  5795. AddAction(eaDeleteText,Pos,Pos,CharStr(' ',k),GetFlags);
  5796. end;
  5797. end;
  5798. { Removes selection if Shift is pressed as well and we do not change cursor position anyway
  5799. SetCurPtr(CurPos.X,CurPos.Y); }
  5800. {after SetCurPtr return PersistentBlocks as it was before}
  5801. { as SetCurPtr commented out, no need take care of Persistent Blocks
  5802. if not WasPersistentBlocks then
  5803. SetFlags(GetFlags and (not longword(efPersistentBlocks)));
  5804. }
  5805. UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
  5806. DrawLines(CurPos.Y);
  5807. SetModified(true);
  5808. CloseGroupedAction(eaUnindentBlock);
  5809. UnLock;
  5810. end;
  5811. procedure TCustomCodeEditor.SelectWord;
  5812. const WordChars = ['A'..'Z','a'..'z','0'..'9','_'];
  5813. var S : String;
  5814. StartPos,EndPos : byte;
  5815. A,B: TPoint;
  5816. begin
  5817. A:=CurPos;
  5818. B:=CurPos;
  5819. S:=GetDisplayText(A.Y);
  5820. StartPos:=A.X+1;
  5821. EndPos:=StartPos;
  5822. if not (S[StartPos] in WordChars) then
  5823. exit
  5824. else
  5825. begin
  5826. While (StartPos>1) and (S[StartPos-1] in WordChars) do
  5827. Dec(StartPos);
  5828. While (EndPos<Length(S)) and (S[EndPos+1] in WordChars) do
  5829. Inc(EndPos);
  5830. A.X:=StartPos-1;
  5831. B.X:=EndPos;
  5832. SetSelection(A,B);
  5833. end;
  5834. end;
  5835. procedure TCustomCodeEditor.SelectLine;
  5836. var A,B: TPoint;
  5837. begin
  5838. if CurPos.Y<GetLineCount then
  5839. begin
  5840. A.Y:=CurPos.Y; A.X:=0;
  5841. B.Y:=CurPos.Y+1; B.X:=0;
  5842. SetSelection(A,B);
  5843. end;
  5844. end;
  5845. procedure TCustomCodeEditor.WriteBlock;
  5846. var FileName: string;
  5847. S: PBufStream;
  5848. begin
  5849. if ValidBlock=false then Exit;
  5850. FileName:='';
  5851. if EditorDialog(edWriteBlock, @FileName) <> cmCancel then
  5852. begin
  5853. FileName := FExpand(FileName);
  5854. New(S, Init(FileName, stCreate, 4096));
  5855. if (S=nil) or (S^.Status<>stOK) then
  5856. EditorDialog(edCreateError,@FileName)
  5857. else
  5858. if SaveAreaToStream(S,SelStart,SelEnd)=false then
  5859. EditorDialog(edWriteError,@FileName);
  5860. if Assigned(S) then Dispose(S, Done);
  5861. end;
  5862. end;
  5863. procedure TCustomCodeEditor.ReadBlock;
  5864. var FileName: string;
  5865. S: PFastBufStream;
  5866. E: PCodeEditor;
  5867. R: TRect;
  5868. begin
  5869. if IsReadOnly then Exit;
  5870. FileName:='';
  5871. if EditorDialog(edReadBlock, @FileName) <> cmCancel then
  5872. begin
  5873. FileName := FExpand(FileName);
  5874. New(S, Init(FileName, stOpenRead, 4096));
  5875. if (S=nil) or (S^.Status<>stOK) then
  5876. EditorDialog(edReadError,@FileName)
  5877. else
  5878. begin
  5879. R.Assign(0,0,0,0);
  5880. New(E, Init(R,nil,nil,nil,nil));
  5881. AddGroupedAction(eaReadBlock);
  5882. if E^.LoadFromStream(S)=false then
  5883. EditorDialog(edReadError,@FileName)
  5884. else
  5885. begin
  5886. E^.SelectAll(true);
  5887. Self.InsertFrom(E);
  5888. end;
  5889. CloseGroupedAction(eaReadBlock);
  5890. Dispose(E, Done);
  5891. end;
  5892. if Assigned(S) then Dispose(S, Done);
  5893. end;
  5894. end;
  5895. procedure TCustomCodeEditor.PrintBlock;
  5896. begin
  5897. NotImplemented; Exit;
  5898. end;
  5899. function TCustomCodeEditor.SelectCodeTemplate(var ShortCut: string): boolean;
  5900. begin
  5901. { Abstract }
  5902. SelectCodeTemplate:=false;
  5903. end;
  5904. procedure TCustomCodeEditor.ExpandCodeTemplate;
  5905. var Line : sw_astring;
  5906. ShortCutInEditor,ShortCut: string;
  5907. X,Y,I,LineIndent: sw_integer;
  5908. CodeLines: PUnsortedStringCollection;
  5909. CanJump: boolean;
  5910. CP: TPoint;
  5911. begin
  5912. {
  5913. The usage of editing primitives in this routine make it pretty slow, but
  5914. its speed is still acceptable and they make the implementation of Undo
  5915. much easier... - Gabor
  5916. }
  5917. if IsReadOnly then Exit;
  5918. Lock;
  5919. CP.X:=-1; CP.Y:=-1;
  5920. Line:=GetDisplayText(CurPos.Y);
  5921. X:=CurPos.X; ShortCut:='';
  5922. if X<=length(Line) then
  5923. while (X>0) and (Line[X] in (NumberChars+AlphaChars)) do
  5924. begin
  5925. ShortCut:=Line[X]+ShortCut;
  5926. Dec(X);
  5927. end;
  5928. ShortCutInEditor:=ShortCut;
  5929. New(CodeLines, Init(10,10));
  5930. if (ShortCut='') or (not TranslateCodeTemplate(ShortCut,CodeLines)) then
  5931. if SelectCodeTemplate(ShortCut) then
  5932. TranslateCodeTemplate(ShortCut,CodeLines);
  5933. if CodeLines^.Count>0 then
  5934. begin
  5935. LineIndent:=X;
  5936. SetCurPtr(X,CurPos.Y);
  5937. if Copy(ShortCut,1,length(ShortCutInEditor))=ShortCutInEditor then
  5938. begin
  5939. for I:=1 to length(ShortCutInEditor) do
  5940. DelChar;
  5941. end
  5942. else
  5943. { restore correct position }
  5944. SetCurPtr(X+Length(ShortCutInEditor),CurPos.Y);
  5945. for Y:=0 to CodeLines^.Count-1 do
  5946. begin
  5947. Line:=GetStr(CodeLines^.At(Y));
  5948. CanJump:=false;
  5949. if (Y>0) then
  5950. begin
  5951. CanJump:=Trim(GetLineText(CurPos.Y))='';
  5952. if CanJump=false then
  5953. begin
  5954. (* for X:=1 to LineIndent do { indent template lines to align }
  5955. AddChar(' '); { them to the first line }*)
  5956. InsertText(CharStr(' ',LineIndent));
  5957. end
  5958. else
  5959. SetCurPtr(CurPos.X+LineIndent,CurPos.Y);
  5960. end;
  5961. I:=Pos(CodeTemplateCursorChar,Line);
  5962. if I>0 then
  5963. begin
  5964. Delete(Line,I,1);
  5965. CP.X:=CurPos.X+I-1;
  5966. CP.Y:=CurPos.Y;
  5967. end;
  5968. InsertText(Line);
  5969. if Y<CodeLines^.Count-1 then
  5970. begin
  5971. InsertNewLine; { line break }
  5972. if CanJump=false then
  5973. begin
  5974. while CurPos.X>0 do { unindent }
  5975. begin
  5976. SetCurPtr(CurPos.X-1,CurPos.Y);
  5977. DelChar;
  5978. end;
  5979. end
  5980. else
  5981. SetCurPtr(0,CurPos.Y);
  5982. end;
  5983. end;
  5984. end;
  5985. Dispose(CodeLines, Done);
  5986. if (CP.X<>-1) and (CP.Y<>-1) then
  5987. SetCurPtr(CP.X,CP.Y);
  5988. UnLock;
  5989. end;
  5990. procedure TCustomCodeEditor.AddChar(C: AnsiChar);
  5991. const OpenBrackets : string[10] = '[({';
  5992. CloseBrackets : string[10] = '])}';
  5993. var S,SC,TabS: sw_astring;
  5994. BI: byte;
  5995. CI,TabStart,LocTabSize : Sw_integer;
  5996. SP: TPoint;
  5997. HoldUndo : boolean;
  5998. begin
  5999. if IsReadOnly then Exit;
  6000. Lock;
  6001. if not (Clipboard=@Self) and IsFlagSet(efOverwriteBlocks) and InSelectionArea then
  6002. DelSelect; {delete selection before}
  6003. SP:=CurPos;
  6004. HoldUndo:=GetStoreUndo;
  6005. SetStoreUndo(false);
  6006. if (C<>TAB) or IsFlagSet(efUseTabCharacters) then
  6007. SC:=C
  6008. else
  6009. begin
  6010. LocTabSize:=GetTabSize - (CurPos.X mod GetTabSize);
  6011. if (CurPos.Y<=1) or not IsFlagSet(efAutoIndent) then
  6012. SC:=CharStr(' ',LocTabSize)
  6013. else
  6014. begin
  6015. S:=GetLineText(CurPos.Y-1);
  6016. BI:=CurPos.X+1;
  6017. while (BI<=Length(S)) and (S[BI]=' ') do
  6018. inc(BI);
  6019. if (BI=CurPos.X+1) or (BI>Length(S)) then
  6020. SC:=CharStr(' ',LocTabSize)
  6021. else
  6022. SC:=CharStr(' ',BI-CurPos.X-1);
  6023. end;
  6024. end;
  6025. S:=GetLineText(CurPos.Y);
  6026. if CharIdxToLinePos(CurPos.Y,length(S))<CurPos.X then
  6027. begin
  6028. S:=S+CharStr(' ',CurPos.X-CharIdxToLinePos(CurPos.Y,length(S)){-1});
  6029. SetLineText(CurPos.Y,S);
  6030. end;
  6031. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  6032. {$if sizeof(sw_astring)>8 only if ShortString}
  6033. if CI>High(S) then
  6034. begin
  6035. Unlock;
  6036. exit;
  6037. end;
  6038. {$endif}
  6039. SP.X:=CharIdxToLinePos(CurPos.Y,CI); {actual changes are going to be here (tab space adjustment)}
  6040. if (CI>0) and (S[CI]=TAB) and not IsFlagSet(efUseTabCharacters) then
  6041. begin
  6042. if CI=1 then
  6043. TabStart:=0
  6044. else
  6045. TabStart:=CharIdxToLinePos(CurPos.Y,CI-1)+1;
  6046. if SC=Tab then TabS:=Tab else
  6047. TabS:=CharStr(' ',CurPos.X-TabStart);
  6048. SetLineText(CurPos.Y,copy(S,1,CI-1)+TabS+SC+copy(S,CI+1,Length(S)));
  6049. SetCurPtr(CharIdxToLinePos(CurPos.Y,CI+length(TabS)+length(SC)),CurPos.Y);
  6050. end
  6051. else
  6052. begin
  6053. if Overwrite and (CI<=length(S)) then
  6054. begin
  6055. SetLineText(CurPos.Y,copy(S,1,CI-1)+SC+copy(S,CI+length(SC),Length(S)));
  6056. end
  6057. else
  6058. SetLineText(CurPos.Y,copy(S,1,CI-1)+SC+copy(S,CI,Length(S)));
  6059. SetCurPtr(CharIdxToLinePos(CurPos.Y,CI+length(SC)),CurPos.Y);
  6060. end;
  6061. { must be before CloseBrackets !! }
  6062. SetStoreUndo(HoldUndo);
  6063. if Overwrite then
  6064. Addaction(eaOverwriteText,SP,CurPos,Copy(S,CI,length(SC)),GetFlags)
  6065. else
  6066. Addaction(eaInsertText,SP,CurPos,SC,GetFlags);
  6067. SetStoreUndo(false);
  6068. if IsFlagSet(efAutoBrackets) then
  6069. begin
  6070. BI:=Pos(C,OpenBrackets);
  6071. if (BI>0) then
  6072. begin
  6073. SetStoreUndo(HoldUndo);
  6074. AddChar(CloseBrackets[BI]);
  6075. SetStoreUndo(false);
  6076. SetCurPtr(CurPos.X-1,CurPos.Y);
  6077. end;
  6078. end;
  6079. UpdateAttrs(CurPos.Y,attrAll);
  6080. if GetInsertMode then
  6081. AdjustSelection(CurPos.X-SP.X,CurPos.Y-SP.Y);
  6082. DrawLines(CurPos.Y);
  6083. SetStoreUndo(HoldUndo);
  6084. SetModified(true);
  6085. UnLock;
  6086. end;
  6087. const
  6088. linelimit = 200;
  6089. procedure TCustomCodeEditor.PasteText(P:PAnsiChar; ASize:sw_integer);
  6090. var
  6091. StorePos : TPoint;
  6092. first : boolean;
  6093. IsNewLine: boolean;
  6094. procedure InsertStringWrap(const s: sw_astring; var i : Longint);
  6095. var
  6096. BPos,EPos: TPoint;
  6097. begin
  6098. if first then
  6099. begin
  6100. { we need to cut the line in two
  6101. if not at end of line PM }
  6102. if IsNewLine then
  6103. InsertNewLine;
  6104. SetCurPtr(StorePos.X,StorePos.Y);
  6105. InsertText(s);
  6106. first:=false;
  6107. end
  6108. else
  6109. begin
  6110. Inc(i);
  6111. if IsNewLine then
  6112. begin
  6113. InsertLine(i,s);
  6114. BPos.X:=0;BPos.Y:=i;
  6115. EPOS.X:=Length(s);EPos.Y:=i;
  6116. AddAction(eaInsertLine,BPos,EPos,GetDisplayText(i),GetFlags);
  6117. end else
  6118. begin
  6119. SetCurPtr(0,i);
  6120. InsertText(s);
  6121. end;
  6122. end;
  6123. end;
  6124. var
  6125. l,i,len,len10 : longint;
  6126. p10,p2,p13 : PAnsiChar;
  6127. s : sw_astring;
  6128. begin
  6129. Lock;
  6130. first:=true;
  6131. StorePos:=CurPos;
  6132. i:=CurPos.Y;
  6133. if ASize>500 then
  6134. PushInfo(msg_readingwinclipboard);
  6135. AddGroupedAction(eaPasteWin);
  6136. if not (Clipboard=@Self) and IsFlagSet(efOverwriteBlocks) and InSelectionArea then
  6137. DelSelect; {delete selection before paste}
  6138. p2:=p;
  6139. len:=strlen(p2);
  6140. // issue lines ((#13)#10 terminated) of maximally "linelimit" chars.
  6141. // does not take initial X position into account
  6142. repeat
  6143. p13:=strpos(p2,#13);
  6144. p10:=strpos(p2,#10);
  6145. {$if sizeof(sw_astring)>8 only if ShortString lines}
  6146. if len> linelimit then
  6147. len:=linelimit;
  6148. {$endif}
  6149. if not assigned(p10) and assigned(p13) then
  6150. p10:=p13;
  6151. IsNewLine:=false;
  6152. if assigned(p10) then
  6153. begin
  6154. IsNewLine:=true;
  6155. len10:=p10-p2;
  6156. if len10<len then
  6157. begin
  6158. if p13+1=p10 then
  6159. dec(len10);
  6160. len:=len10;
  6161. end
  6162. else
  6163. p10:=nil; // signal no cleanup
  6164. end;
  6165. setlength(s,len);
  6166. if len>0 then
  6167. move(p2^,s[1],len);
  6168. // cleanup
  6169. if assigned(p10) then
  6170. p2:=p10+1
  6171. else
  6172. inc(p2,len);
  6173. insertstringwrap(s,i);
  6174. len:=strlen(p2);
  6175. until len=0;
  6176. SetCurPtr(StorePos.X,StorePos.Y); // y+i to get after paste?
  6177. SetModified(true);
  6178. UpdateAttrs(StorePos.Y,attrAll);
  6179. CloseGroupedAction(eaPasteWin);
  6180. Update;
  6181. if ASize>500 then
  6182. PopInfo;
  6183. DrawView;
  6184. UnLock;
  6185. end;
  6186. {$ifdef WinClipSupported}
  6187. function TCustomCodeEditor.ClipPasteWin: Boolean;
  6188. var
  6189. OK: boolean;
  6190. l : longint;
  6191. p : PAnsiChar;
  6192. begin
  6193. Lock;
  6194. OK:=WinClipboardSupported;
  6195. if OK then
  6196. begin
  6197. l:=GetTextWinClipboardSize;
  6198. if l=0 then
  6199. OK:=false
  6200. else
  6201. OK:=GetTextWinClipBoardData(p,l);
  6202. if OK and assigned(p) then
  6203. begin
  6204. PasteText(p,l);
  6205. { we must free the allocated memory }
  6206. freemem(p,l);
  6207. end;
  6208. end;
  6209. ClipPasteWin:=OK;
  6210. UnLock;
  6211. end;
  6212. function TCustomCodeEditor.ClipCopyWin: Boolean;
  6213. var OK,ShowInfo: boolean;
  6214. p,p2 : PAnsiChar;
  6215. s : sw_astring;
  6216. i,str_begin,str_end,NumLines,PcLength : longint;
  6217. begin
  6218. NumLines:=SelEnd.Y-SelStart.Y;
  6219. if (NumLines>0) or (SelEnd.X>SelStart.X) then
  6220. Inc(NumLines);
  6221. if NumLines=0 then
  6222. exit;
  6223. Lock;
  6224. ShowInfo:=SelEnd.Y-SelStart.Y>50;
  6225. if ShowInfo then
  6226. PushInfo(msg_copyingwinclipboard);
  6227. { First calculate needed size }
  6228. { for newlines first + 1 for terminal #0 }
  6229. PcLength:=Length(EOL)*(NumLines-1)+1;
  6230. { overestimated but can not be that big PM }
  6231. for i:=SelStart.Y to SelEnd.Y do
  6232. PCLength:=PCLength+Length(GetLineText(i));
  6233. getmem(p,PCLength);
  6234. i:=SelStart.Y;
  6235. s:=GetLineText(i);
  6236. str_begin:=LinePosToCharIdx(i,SelStart.X);
  6237. if SelEnd.Y>SelStart.Y then
  6238. str_end:=Length(S)
  6239. else
  6240. str_end:=LinePosToCharIdx(i,SelEnd.X)-1;
  6241. s:=copy(s,str_begin,str_end-str_begin+1);
  6242. {$if sizeof(sw_astring)>8}
  6243. strpcopy(p,s);
  6244. {$else}
  6245. s:=s+#0;
  6246. Move(S[1],P^,Length(S));
  6247. {$endif}
  6248. p2:=strend(p);
  6249. inc(i);
  6250. while i<SelEnd.Y do
  6251. begin
  6252. s:=EOL+GetLineText(i);
  6253. {$if sizeof(sw_astring)>8}
  6254. strpcopy(p2,s);
  6255. {$else}
  6256. s:=s+#0;
  6257. Move(S[1],P2^,Length(S));
  6258. {$endif}
  6259. p2:=strend(p2);
  6260. Inc(i);
  6261. end;
  6262. if SelEnd.Y>SelStart.Y then
  6263. begin
  6264. s:=copy(GetLineText(i),1,LinePosToCharIdx(i,SelEnd.X)-1);
  6265. {$if sizeof(sw_astring)>8}
  6266. strpcopy(p2,EOL+s);
  6267. {$else}
  6268. s:=EOL+s+#0;
  6269. Move(S[1],P2^,Length(S));
  6270. {$endif}
  6271. end;
  6272. OK:=WinClipboardSupported;
  6273. if OK then
  6274. begin
  6275. OK:=SetTextWinClipBoardData(p,strlen(p));
  6276. end;
  6277. ClipCopyWin:=OK;
  6278. if ShowInfo then
  6279. PopInfo;
  6280. Freemem(p,PCLength);
  6281. UnLock;
  6282. end;
  6283. {$endif WinClipSupported}
  6284. function TCustomCodeEditor.ClipCopy: Boolean;
  6285. var ShowInfo,CanPaste: boolean;
  6286. begin
  6287. Lock;
  6288. {AddGroupedAction(eaCopy);
  6289. can we undo a copy ??
  6290. maybe as an Undo Paste in Clipboard !! }
  6291. clipcopy:=false;
  6292. showinfo:=false;
  6293. if (clipboard<>nil) and (clipboard<>@self) then
  6294. begin
  6295. ShowInfo:=SelEnd.Y-SelStart.Y>50;
  6296. if ShowInfo then
  6297. PushInfo(msg_copyingclipboard);
  6298. clipcopy:=Clipboard^.InsertFrom(@Self);
  6299. if ShowInfo then
  6300. PopInfo;
  6301. {Enable paste command.}
  6302. CanPaste:=((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
  6303. (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
  6304. SetCmdState(FromClipCmds,CanPaste);
  6305. end;
  6306. UnLock;
  6307. end;
  6308. procedure TCustomCodeEditor.ClipCut;
  6309. var
  6310. ShowInfo,CanPaste : boolean;
  6311. begin
  6312. if IsReadOnly then Exit;
  6313. Lock;
  6314. AddGroupedAction(eaCut);
  6315. DontConsiderShiftState:=true;
  6316. if (clipboard<>nil) and (clipboard<>@self) then
  6317. begin
  6318. ShowInfo:=SelEnd.Y-SelStart.Y>50;
  6319. if ShowInfo then
  6320. PushInfo(msg_cutting);
  6321. if Clipboard^.InsertFrom(@Self) then
  6322. begin
  6323. if not IsClipBoard then
  6324. DelSelect;
  6325. SetModified(true);
  6326. end;
  6327. if ShowInfo then
  6328. PopInfo;
  6329. CanPaste:=((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
  6330. (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
  6331. SetCmdState(FromClipCmds,CanPaste);
  6332. end;
  6333. CloseGroupedAction(eaCut);
  6334. UnLock;
  6335. DontConsiderShiftState:=false;
  6336. end;
  6337. procedure TCustomCodeEditor.ClipPaste;
  6338. var
  6339. ShowInfo : boolean;
  6340. begin
  6341. if IsReadOnly then Exit;
  6342. DontConsiderShiftState:=true;
  6343. Lock;
  6344. AddGroupedAction(eaPaste);
  6345. if Clipboard<>nil then
  6346. begin
  6347. ShowInfo:=Clipboard^.SelEnd.Y-Clipboard^.SelStart.Y>50;
  6348. if ShowInfo then
  6349. PushInfo(msg_pastingclipboard);
  6350. InsertFrom(Clipboard);
  6351. if ShowInfo then
  6352. PopInfo;
  6353. end;
  6354. CloseGroupedAction(eaPaste);
  6355. UnLock;
  6356. DontConsiderShiftState:=false;
  6357. end;
  6358. procedure TCustomCodeEditor.Undo;
  6359. begin
  6360. NotImplemented; Exit;
  6361. end;
  6362. procedure TCustomCodeEditor.Redo;
  6363. begin
  6364. NotImplemented; Exit;
  6365. end;
  6366. procedure TCustomCodeEditor.GotoLine;
  6367. const
  6368. GotoRec: TGotoLineDialogRec = (LineNo:'1';Lines:0); {keep previous goto line number}
  6369. begin
  6370. with GotoRec do
  6371. begin
  6372. Lines:=GetLineCount;
  6373. {Linecount can be 0, but in that case there still is a cursor blinking in top
  6374. of the window, which will become line 1 as soon as someone hits a key.}
  6375. if lines=0 then
  6376. lines:=1;
  6377. if EditorDialog(edGotoLine, @GotoRec) <> cmCancel then
  6378. begin
  6379. Lock;
  6380. SetCurPtr(0,StrToInt(LineNo)-1);
  6381. TrackCursor(do_centre);
  6382. UnLock;
  6383. end;
  6384. end;
  6385. end;
  6386. procedure TCustomCodeEditor.Find;
  6387. var
  6388. FindRec: TFindDialogRec;
  6389. DoConf: boolean;
  6390. CurrentWord : string;
  6391. begin
  6392. with FindRec do
  6393. begin
  6394. Find := FindStr;
  6395. CurrentWord:=GetCurrentWord;
  6396. if CurrentWord<>'' then
  6397. Find:=CurrentWord;
  6398. {$ifdef TEST_REGEXP}
  6399. Options := ((FindFlags and ffmOptionsFind) shr ffsOptions) or
  6400. ((FindFlags and ffUseRegExp) shr ffsUseRegExpFind);
  6401. {$else not TEST_REGEXP}
  6402. Options := (FindFlags and ffmOptions) shr ffsOptions;
  6403. {$endif TEST_REGEXP}
  6404. Direction := (FindFlags and ffmDirection) shr ffsDirection;
  6405. Scope := (FindFlags and ffmScope) shr ffsScope;
  6406. Origin := (FindFlags and ffmOrigin) shr ffsOrigin;
  6407. DoConf:= (FindFlags and ffPromptOnReplace)<>0;
  6408. FindReplaceEditor:=@self;
  6409. if EditorDialog(edFind, @FindRec) <> cmCancel then
  6410. begin
  6411. FindStr := Find;
  6412. {$ifdef TEST_REGEXP}
  6413. FindFlags := ((Options and ffmOptionsFind) shl ffsOptions) or (Direction shl ffsDirection) or
  6414. ((Options and ffmUseRegExpFind) shl ffsUseRegExpFind) or
  6415. (Scope shl ffsScope) or (Origin shl ffsOrigin);
  6416. {$else : not TEST_REGEXP}
  6417. FindFlags := ((Options and ffmOptions) shl ffsOptions) or (Direction shl ffsDirection) or
  6418. (Scope shl ffsScope) or (Origin shl ffsOrigin);
  6419. {$endif TEST_REGEXP}
  6420. FindFlags := FindFlags and not ffDoReplace;
  6421. if DoConf then
  6422. FindFlags := (FindFlags or ffPromptOnReplace);
  6423. SearchRunCount:=0;
  6424. if FindStr<>'' then
  6425. DoSearchReplace
  6426. else
  6427. EditorDialog(edSearchFailed,nil);
  6428. end;
  6429. FindReplaceEditor:=nil;
  6430. end;
  6431. end;
  6432. procedure TCustomCodeEditor.Replace;
  6433. var
  6434. ReplaceRec: TReplaceDialogRec;
  6435. Re: word;
  6436. begin
  6437. if IsReadOnly then Exit;
  6438. with ReplaceRec do
  6439. begin
  6440. Find := FindStr;
  6441. if GetCurrentWord<>'' then
  6442. Find:=GetCurrentWord;
  6443. Replace := ReplaceStr;
  6444. {$ifdef TEST_REGEXP}
  6445. Options := (FindFlags and ffmOptions) shr ffsOptions or
  6446. (FindFlags and ffUseRegExp) shr ffsUseRegExpReplace;
  6447. {$else not TEST_REGEXP}
  6448. Options := (FindFlags and ffmOptions) shr ffsOptions;
  6449. {$endif TEST_REGEXP}
  6450. Direction := (FindFlags and ffmDirection) shr ffsDirection;
  6451. Scope := (FindFlags and ffmScope) shr ffsScope;
  6452. Origin := (FindFlags and ffmOrigin) shr ffsOrigin;
  6453. FindReplaceEditor:=@self;
  6454. Re:=EditorDialog(edReplace, @ReplaceRec);
  6455. FindReplaceEditor:=nil;
  6456. if Re <> cmCancel then
  6457. begin
  6458. FindStr := Find;
  6459. ReplaceStr := Replace;
  6460. FindFlags := (Options shl ffsOptions) or (Direction shl ffsDirection) or
  6461. {$ifdef TEST_REGEXP}
  6462. ((Options and ffmUseRegExpReplace) shl ffsUseRegExpReplace) or
  6463. {$endif TEST_REGEXP}
  6464. (Scope shl ffsScope) or (Origin shl ffsOrigin);
  6465. FindFlags := FindFlags or ffDoReplace;
  6466. if Re = cmYes then
  6467. FindFlags := FindFlags or ffReplaceAll;
  6468. SearchRunCount:=0;
  6469. if FindStr<>'' then
  6470. DoSearchReplace
  6471. else
  6472. EditorDialog(edSearchFailed,nil);
  6473. end;
  6474. end;
  6475. end;
  6476. procedure TCustomCodeEditor.DoSearchReplace;
  6477. var S: sw_astring;
  6478. DX,DY,P,Y,X: sw_integer;
  6479. Count: sw_integer;
  6480. Found,CanExit: boolean;
  6481. SForward,DoReplace,DoReplaceAll: boolean;
  6482. {$ifdef TEST_REGEXP}
  6483. UseRegExp : boolean;
  6484. RegExpEngine : TRegExprEngine;
  6485. RegExpFlags : tregexprflags;
  6486. regexpindex,regexplen : longint;
  6487. findstrpchar : PAnsiChar;
  6488. {$endif TEST_REGEXP}
  6489. LeftOK,RightOK: boolean;
  6490. FoundCount: sw_integer;
  6491. A,B: TPoint;
  6492. AreaStart,AreaEnd: TPoint;
  6493. CanReplace,Confirm: boolean;
  6494. Re: word;
  6495. IFindStr : string;
  6496. BT : BTable;
  6497. Overwriting : boolean;
  6498. function ContainsText(const SubS:string;var S: sw_astring; Start: Sw_integer): Sw_integer;
  6499. var
  6500. P: Sw_Integer;
  6501. begin
  6502. if Start<=0 then
  6503. P:=0
  6504. else
  6505. begin
  6506. if SForward then
  6507. begin
  6508. if Start>length(s) then
  6509. P:=0
  6510. else if FindFlags and ffCaseSensitive<>0 then
  6511. P:=BMFScan(S[Start],length(s)+1-Start,FindStr,Bt)+1
  6512. else
  6513. P:=BMFIScan(S[Start],length(s)+1-Start,IFindStr,Bt)+1;
  6514. if P>0 then
  6515. Inc(P,Start-1);
  6516. end
  6517. else
  6518. begin
  6519. if start>length(s) then
  6520. start:=length(s);
  6521. if FindFlags and ffCaseSensitive<>0 then
  6522. P:=BMBScan(S[1],Start,FindStr,Bt)+1
  6523. else
  6524. P:=BMBIScan(S[1],Start,IFindStr,Bt)+1;
  6525. end;
  6526. end;
  6527. ContainsText:=P;
  6528. end;
  6529. function InArea(X,Y: sw_integer): boolean;
  6530. begin
  6531. InArea:=((AreaStart.Y=Y) and (AreaStart.X<=X)) or
  6532. ((AreaStart.Y<Y) and (Y<AreaEnd.Y)) or
  6533. ((AreaEnd.Y=Y) and (X<=AreaEnd.X));
  6534. end;
  6535. var CurDY: sw_integer;
  6536. begin
  6537. if FindStr='' then
  6538. begin
  6539. Find;
  6540. { Find will call DoFindReplace at end again
  6541. so we need to exit directly now PM }
  6542. exit;
  6543. end;
  6544. Inc(SearchRunCount);
  6545. SForward:=(FindFlags and ffmDirection)=ffForward;
  6546. DoReplace:=(FindFlags and ffDoReplace)<>0;
  6547. Confirm:=(FindFlags and ffPromptOnReplace)<>0;
  6548. DoReplaceAll:=(FindFlags and ffReplaceAll)<>0;
  6549. {$ifdef TEST_REGEXP}
  6550. UseRegExp:=(FindFlags and ffUseRegExp)<>0;
  6551. if UseRegExp then
  6552. begin
  6553. if FindFlags and ffCaseSensitive<>0 then
  6554. RegExpFlags:=[ref_caseinsensitive]
  6555. else
  6556. RegExpFlags:=[];
  6557. getmem(findstrpchar,length(findstr)+1);
  6558. strpcopy(findstrpchar,findstr);
  6559. RegExpEngine:=GenerateRegExprEngine(findstrpchar,RegExpFlags);
  6560. strdispose(findstrpchar);
  6561. end;
  6562. {$endif TEST_REGEXP}
  6563. Count:=GetLineCount;
  6564. FoundCount:=0;
  6565. { Empty file ? }
  6566. if Count=0 then
  6567. begin
  6568. EditorDialog(edSearchFailed,nil);
  6569. exit;
  6570. end;
  6571. if SForward then
  6572. DY:=1
  6573. else
  6574. DY:=-1;
  6575. DX:=DY;
  6576. if FindStr<>'' then
  6577. PushInfo('Looking for "'+FindStr+'"');
  6578. if (FindFlags and ffmScope)=ffGlobal then
  6579. begin
  6580. AreaStart.X:=0;
  6581. AreaStart.Y:=0;
  6582. AreaEnd.X:=length(GetDisplayText(Count-1));
  6583. AreaEnd.Y:=Count-1;
  6584. end
  6585. else
  6586. begin
  6587. AreaStart:=SelStart;
  6588. AreaEnd:=SelEnd;
  6589. end;
  6590. { set a y value being inside the areal }
  6591. Y:=Min(CurPos.Y,Count-1);
  6592. if sForward then
  6593. X:=CurPos.X-1
  6594. else
  6595. { if you change this, pleas check that repeated backward searching for single chars still works
  6596. and that data is still found if searching starts outside the current line }
  6597. X:=Min(CurPos.X,length(GetDisplayText(Y)));
  6598. if SearchRunCount=1 then
  6599. if (FindFlags and ffmOrigin)=ffEntireScope then
  6600. if SForward then
  6601. begin
  6602. X:=AreaStart.X-1;
  6603. Y:=AreaStart.Y;
  6604. end
  6605. else
  6606. begin
  6607. X:=AreaEnd.X+1;
  6608. Y:=AreaEnd.Y;
  6609. end;
  6610. if FindFlags and ffCaseSensitive<>0 then
  6611. begin
  6612. if SForward then
  6613. BMFMakeTable(FindStr,bt)
  6614. else
  6615. BMBMakeTable(FindStr,bt);
  6616. end
  6617. else
  6618. begin
  6619. IFindStr:=upcase(FindStr);
  6620. if SForward then
  6621. BMFMakeTable(IFindStr,bt)
  6622. else
  6623. BMBMakeTable(IFindStr,bt);
  6624. end;
  6625. inc(X,DX);
  6626. CanExit:=false;
  6627. if not DoReplace or (not Confirm and (Owner<>nil)) then
  6628. Owner^.Lock;
  6629. if InArea(X,Y) then
  6630. repeat
  6631. CurDY:=DY;
  6632. S:=GetDisplayText(Y);
  6633. if X>length(S)-1 then
  6634. X:=length(S)-1;
  6635. {$ifdef TEST_REGEXP}
  6636. if UseRegExp then
  6637. begin
  6638. getmem(findstrpchar,length(Copy(S,X+1,Length(S)))+1);
  6639. strpcopy(findstrpchar,Copy(S,X+1,Length(S)));
  6640. { If start of line is required do check other positions PM }
  6641. if (FindStr[1]='^') and (X<>0) then
  6642. Found:=false
  6643. else
  6644. Found:=RegExprPos(RegExpEngine,findstrpchar,regexpindex,regexplen);
  6645. strdispose(findstrpchar);
  6646. P:=regexpindex+X+1;
  6647. end
  6648. else
  6649. {$endif TEST_REGEXP}
  6650. begin
  6651. P:=ContainsText(FindStr,S,X+1);
  6652. Found:=P<>0;
  6653. end;
  6654. if Found then
  6655. begin
  6656. A.X:=P-1;
  6657. A.Y:=Y;
  6658. B.Y:=Y;
  6659. {$ifdef TEST_REGEXP}
  6660. if UseRegExp then
  6661. B.X:=A.X+regexplen
  6662. else
  6663. {$endif TEST_REGEXP}
  6664. B.X:=A.X+length(FindStr);
  6665. end;
  6666. Found:=Found and InArea(A.X,A.Y);
  6667. if Found and ((FindFlags and ffWholeWordsOnly)<>0) then
  6668. begin
  6669. LeftOK:=(A.X<=0) or (not( (S[A.X] in AlphaChars+NumberChars) ));
  6670. RightOK:=(B.X>=length(S)) or (not( (S[B.X+1] in AlphaChars+NumberChars) ));
  6671. Found:=LeftOK and RightOK;
  6672. if not Found then
  6673. begin
  6674. CurDY:=0;
  6675. If SForward then
  6676. begin
  6677. X:=B.X+1;
  6678. if X>length(S) then
  6679. CurDY:=DY;
  6680. end
  6681. else
  6682. begin
  6683. X:=A.X-1;
  6684. if X<0 then
  6685. CurDY:=DY;
  6686. end;
  6687. end;
  6688. end;
  6689. if Found then
  6690. begin
  6691. Inc(FoundCount);
  6692. Lock;
  6693. if SForward then
  6694. SetCurPtr(B.X,B.Y)
  6695. else
  6696. SetCurPtr(A.X,A.Y);
  6697. TrackCursor(do_centre);
  6698. SetHighlight(A,B);
  6699. UnLock;
  6700. CurDY:=0;
  6701. if not DoReplace then
  6702. begin
  6703. CanExit:=true;
  6704. If SForward then
  6705. begin
  6706. X:=B.X;
  6707. Y:=B.Y;
  6708. end
  6709. else
  6710. begin
  6711. X:=A.X;
  6712. Y:=A.Y;
  6713. end;
  6714. end
  6715. else
  6716. begin
  6717. if not confirm then
  6718. CanReplace:=true
  6719. else
  6720. begin
  6721. Re:=EditorDialog(edReplacePrompt,@CurPos);
  6722. case Re of
  6723. cmYes :
  6724. CanReplace:=true;
  6725. cmNo :
  6726. CanReplace:=false;
  6727. else {cmCancel}
  6728. begin
  6729. CanReplace:=false;
  6730. CanExit:=true;
  6731. end;
  6732. end;
  6733. end;
  6734. if CanReplace then
  6735. begin
  6736. Lock;
  6737. { don't use SetInsertMode here because it changes the cursor shape }
  6738. overwriting:=(GetFlags and efInsertMode)=0;
  6739. SetFlags(GetFlags or efInsertMode);
  6740. SetSelection(A,B);
  6741. DelSelect;
  6742. InsertText(ReplaceStr);
  6743. if SForward then
  6744. begin
  6745. X:=CurPos.X;
  6746. Y:=CurPos.Y;
  6747. end
  6748. else
  6749. begin
  6750. X:=A.X;
  6751. Y:=A.Y;
  6752. end;
  6753. if overwriting then
  6754. SetFlags(GetFlags and (not efInsertMode));
  6755. UnLock;
  6756. end
  6757. else
  6758. begin
  6759. If SForward then
  6760. begin
  6761. X:=B.X;
  6762. Y:=B.Y;
  6763. end
  6764. else
  6765. begin
  6766. X:=A.X;
  6767. Y:=A.Y;
  6768. end;
  6769. end;
  6770. if (DoReplaceAll=false) then
  6771. CanExit:=true;
  6772. end;
  6773. end;
  6774. if (CanExit=false) and (CurDY<>0) then
  6775. begin
  6776. inc(Y,CurDY);
  6777. if SForward then
  6778. X:=0
  6779. else
  6780. X:=254;
  6781. CanExit:=((Y>=Count) and sForward) or (Y<0);
  6782. end;
  6783. if not CanExit then
  6784. CanExit:=(not InArea(X,Y)) and sForward;
  6785. until CanExit;
  6786. if (FoundCount=0) or (DoReplace) then
  6787. SetHighlight(CurPos,CurPos);
  6788. if (DoReplace=false) or ((Confirm=false) and (Owner<>nil)) then
  6789. Owner^.UnLock;
  6790. {if (DoReplace=false) or (Confirm=false) then
  6791. UnLock;}
  6792. if (FoundCount=0) then
  6793. EditorDialog(edSearchFailed,nil);
  6794. if FindStr<>'' then
  6795. PopInfo;
  6796. {$ifdef TEST_REGEXP}
  6797. if UseRegExp then
  6798. DestroyRegExprEngine(RegExpEngine);
  6799. {$endif TEST_REGEXP}
  6800. if (FindFlags and ffmScope)=ffSelectedText then
  6801. { restore selection PM }
  6802. begin
  6803. SetSelection(AreaStart,AreaEnd);
  6804. end;
  6805. end;
  6806. function TCustomCodeEditor.GetAutoBrackets: boolean;
  6807. begin
  6808. GetAutoBrackets:=(GetFlags and efAutoBrackets)<>0;
  6809. end;
  6810. procedure TCustomCodeEditor.SetAutoBrackets(AutoBrackets: boolean);
  6811. begin
  6812. if AutoBrackets then
  6813. SetFlags(GetFlags or efAutoBrackets)
  6814. else
  6815. SetFlags(GetFlags and (not efAutoBrackets));
  6816. end;
  6817. function TCustomCodeEditor.GetInsertMode: boolean;
  6818. begin
  6819. GetInsertMode:=(GetFlags and efInsertMode)<>0;
  6820. end;
  6821. procedure TCustomCodeEditor.SetInsertMode(InsertMode: boolean);
  6822. begin
  6823. if InsertMode then
  6824. SetFlags(GetFlags or efInsertMode)
  6825. else
  6826. SetFlags(GetFlags and (not efInsertMode));
  6827. DrawCursor;
  6828. end;
  6829. { there is a problem with ShiftDel here
  6830. because GetShitState tells to extend the
  6831. selection which gives wrong results (PM) }
  6832. function TCustomCodeEditor.ShouldExtend: boolean;
  6833. var ShiftInEvent: boolean;
  6834. begin
  6835. ShiftInEvent:=false;
  6836. if Assigned(CurEvent) then
  6837. if CurEvent^.What=evKeyDown then
  6838. ShiftInEvent:=((CurEvent^.KeyShift and kbShift)<>0);
  6839. ShouldExtend:=ShiftInEvent and
  6840. not DontConsiderShiftState;
  6841. end;
  6842. procedure TCustomCodeEditor.SetCurPtr(X,Y: sw_integer);
  6843. var OldPos{,OldSEnd,OldSStart}: TPoint;
  6844. Extended: boolean;
  6845. F: PFold;
  6846. begin
  6847. Lock;
  6848. X:=Max(0,Min(MaxLineLength+1,X));
  6849. Y:=Max(0,Min(GetLineCount-1,Y));
  6850. OldPos:=CurPos;
  6851. { OldSEnd:=SelEnd;
  6852. OldSStart:=SelStart;}
  6853. CurPos.X:=X;
  6854. CurPos.Y:=Y;
  6855. TrackCursor(do_not_centre);
  6856. if not IsLineVisible(CurPos.Y) then
  6857. begin
  6858. F:=GetLineFold(CurPos.Y);
  6859. if Assigned(F) then
  6860. F^.Collapse(false);
  6861. end;
  6862. if not NoSelect and ShouldExtend then
  6863. begin
  6864. CheckSels;
  6865. Extended:=false;
  6866. if PointOfs(OldPos)=PointOfs(SelStart) then
  6867. begin
  6868. SetSelection(CurPos,SelEnd);
  6869. Extended:=true;
  6870. end;
  6871. CheckSels;
  6872. if Extended=false then
  6873. if PointOfs(OldPos)=PointOfs(SelEnd) then
  6874. begin
  6875. if not ValidBlock then
  6876. SetSelection(CurPos,CurPos);
  6877. SetSelection(SelStart,CurPos); Extended:=true;
  6878. end;
  6879. CheckSels;
  6880. if not Extended then
  6881. if PointOfs(OldPos)<=PointOfs(CurPos) then
  6882. begin
  6883. SetSelection(OldPos,CurPos);
  6884. Extended:=true;
  6885. end
  6886. else
  6887. begin
  6888. SetSelection(CurPos,OldPos);
  6889. Extended:=true;
  6890. end;
  6891. DrawView;
  6892. end
  6893. else if not IsFlagSet(efPersistentBlocks) then
  6894. begin
  6895. HideSelect;
  6896. DrawView;
  6897. end;
  6898. { if PointOfs(SelStart)=PointOfs(SelEnd) then
  6899. SetSelection(CurPos,CurPos);}
  6900. if (GetFlags and (efHighlightColumn+efHighlightRow))<>0 then
  6901. DrawView;
  6902. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and
  6903. ((Highlight.A.X<>HighLight.B.X) or (Highlight.A.Y<>HighLight.B.Y)) then
  6904. HideHighlight;
  6905. if (OldPos.Y<>CurPos.Y) and (0<=OldPos.Y) and (OldPos.Y<GetLineCount) then
  6906. SetLineText(OldPos.Y,RTrim(GetLineText(OldPos.Y),not IsFlagSet(efUseTabCharacters)));
  6907. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and (GetErrorMessage<>'') then
  6908. SetErrorMessage('');
  6909. { if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and (HighlightRow<>-1) then
  6910. SetHighlightRow(-1);}
  6911. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) then
  6912. AddAction(eaMoveCursor,OldPos,CurPos,'',GetFlags);
  6913. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) then
  6914. PositionChanged;{UpdateIndicator;}
  6915. UnLock;
  6916. end;
  6917. procedure TCustomCodeEditor.CheckSels;
  6918. begin
  6919. if (SelStart.Y>SelEnd.Y) or
  6920. ( (SelStart.Y=SelEnd.Y) and (SelStart.X>SelEnd.X) ) then
  6921. SetSelection(SelEnd,SelStart);
  6922. end;
  6923. procedure TCustomCodeEditor.CodeCompleteApply;
  6924. var S: string;
  6925. FragLen,
  6926. I: integer;
  6927. begin
  6928. Lock;
  6929. { here should be some kind or "mark" or "break" inserted in the Undo
  6930. information, so activating it "undoes" only the completion first and
  6931. doesn't delete the complete word at once... - Gabor }
  6932. FragLen:=Length(GetCodeCompleteFrag);
  6933. S:=GetCodeCompleteWord;
  6934. for I:=FragLen+1 to length(S) do
  6935. AddChar(S[I]);
  6936. UnLock;
  6937. SetCompleteState(csInactive);
  6938. end;
  6939. procedure TCustomCodeEditor.CodeCompleteCancel;
  6940. begin
  6941. SetCompleteState(csDenied);
  6942. end;
  6943. procedure TCustomCodeEditor.CodeCompleteCheck;
  6944. var Line: string;
  6945. X: sw_integer;
  6946. CurWord,NewWord: string;
  6947. begin
  6948. SetCodeCompleteFrag('');
  6949. if (not IsFlagSet(efCodeComplete)) or (IsReadOnly=true) then Exit;
  6950. Lock;
  6951. Line:=GetDisplayText(CurPos.Y);
  6952. X:=CurPos.X; CurWord:='';
  6953. if X<=length(Line) then
  6954. while (X>0) and (Line[X] in (NumberChars+AlphaChars)) do
  6955. begin
  6956. CurWord:=Line[X]+CurWord;
  6957. Dec(X);
  6958. end;
  6959. if (length(CurWord)>=CodeCompleteMinLen) and CompleteCodeWord(CurWord,NewWord) then
  6960. begin
  6961. SetCodeCompleteFrag(CurWord);
  6962. SetCodeCompleteWord(NewWord);
  6963. end
  6964. else
  6965. ClearCodeCompleteWord;
  6966. UnLock;
  6967. end;
  6968. function TCustomCodeEditor.GetCodeCompleteFrag: string;
  6969. begin
  6970. { Abstract }
  6971. GetCodeCompleteFrag:='';
  6972. end;
  6973. procedure TCustomCodeEditor.SetCodeCompleteFrag(const S: string);
  6974. begin
  6975. { Abstract }
  6976. end;
  6977. procedure TCustomCodeEditor.DrawLines(FirstLine: sw_integer);
  6978. begin
  6979. if FirstLine>=(Delta.Y+Size.Y) then Exit; { falls outside of the screen }
  6980. DrawView;
  6981. end;
  6982. procedure TCustomCodeEditor.HideHighlight;
  6983. begin
  6984. SetHighlight(CurPos,CurPos);
  6985. end;
  6986. function TCustomCodeEditor.InSelectionArea:boolean; {CurPos in selection area}
  6987. begin
  6988. InSelectionArea:=false;
  6989. if ((SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y)) then {there is selection}
  6990. begin
  6991. if (SelStart.Y = SelEnd.Y) and (CurPos.X>=min(SelStart.X,SelEnd.X)) and (CurPos.X<=max(SelStart.X,SelEnd.X)) then
  6992. InSelectionArea:=true {select in one line}
  6993. else if (CurPos.Y>min(SelStart.Y,SelEnd.Y)) and (CurPos.Y<max(SelStart.Y,SelEnd.Y)) then
  6994. InSelectionArea:=true {between first and last selected line}
  6995. else if (SelStart.Y < SelEnd.Y) and ( ((SelStart.Y=CurPos.Y) and (SelStart.X<=CurPos.X)) or ((SelEnd.Y=CurPos.Y) and (SelEnd.X>=CurPos.X))) then
  6996. InSelectionArea:=true {in first line or last line}
  6997. else if (SelStart.Y > SelEnd.Y) and ( ((SelStart.Y=CurPos.Y) and (SelStart.X>=CurPos.X)) or ((SelEnd.Y=CurPos.Y) and (SelEnd.X<=CurPos.X))) then
  6998. InSelectionArea:=true; {in first line or last line (selection Start and End reverse)}
  6999. end;
  7000. end;
  7001. procedure TCustomCodeEditor.GetSelectionArea(var StartP,EndP: TPoint);
  7002. begin
  7003. StartP:=SelStart; EndP:=SelEnd;
  7004. if EndP.X=0 then
  7005. begin
  7006. Dec(EndP.Y);
  7007. EndP.X:=length(GetDisplayText(EndP.Y))-1;
  7008. end
  7009. else
  7010. Dec(EndP.X);
  7011. end;
  7012. function TCustomCodeEditor.ValidBlock: boolean;
  7013. begin
  7014. ValidBlock:=(SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y);
  7015. end;
  7016. procedure TCustomCodeEditor.SetSelection(A, B: TPoint);
  7017. var WV: boolean;
  7018. OS,OE: TPoint;
  7019. begin
  7020. WV:=ValidBlock;
  7021. OS:=SelStart; OE:=SelEnd;
  7022. SelStart:=A; SelEnd:=B;
  7023. if (WV=false) and (ValidBlock=false) then { do nothing } else
  7024. if (OS.X<>SelStart.X) or (OS.Y<>SelStart.Y) or
  7025. (OE.X<>SelEnd.X) or (OE.Y<>SelEnd.Y) then
  7026. SelectionChanged;
  7027. end;
  7028. procedure TCustomCodeEditor.SetHighlight(A, B: TPoint);
  7029. begin
  7030. Highlight.A:=A; Highlight.B:=B;
  7031. HighlightChanged;
  7032. end;
  7033. {procedure TCustomCodeEditor.SetHighlightRow(Row: sw_integer);
  7034. begin
  7035. HighlightRow:=Row;
  7036. DrawView;
  7037. end;}
  7038. {procedure TCodeEditor.SetDebuggerRow(Row: sw_integer);
  7039. begin
  7040. DebuggerRow:=Row;
  7041. DrawView;
  7042. end;}
  7043. procedure TCustomCodeEditor.SelectAll(Enable: boolean);
  7044. var A,B: TPoint;
  7045. begin
  7046. if (Enable=false) or (GetLineCount=0) then
  7047. begin A:=CurPos; B:=CurPos end
  7048. else
  7049. begin
  7050. A.X:=0; A.Y:=0;
  7051. { B.Y:=GetLineCount-1;
  7052. B.X:=length(GetLineText(B.Y));}
  7053. B.Y:=GetLineCount; B.X:=0;
  7054. end;
  7055. SetSelection(A,B);
  7056. DrawView;
  7057. end;
  7058. procedure TCustomCodeEditor.CommentSel;
  7059. var
  7060. ey,i : Sw_Integer;
  7061. S,Ind : Sw_AString;
  7062. Pos : Tpoint;
  7063. WasPersistentBlocks : boolean;
  7064. WhiteLen, k : Sw_Integer;
  7065. LLen : Sw_Integer; { length of longest line }
  7066. begin
  7067. if IsReadOnly then Exit;
  7068. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  7069. Lock;
  7070. ey:=SelEnd.Y;
  7071. if SelEnd.X=0 then
  7072. dec(ey);
  7073. S:='';
  7074. { Find shortest white space of beginning of line from all lines
  7075. for simplicity reason Tab is not recognized as white space in this regard }
  7076. LLen:=0;
  7077. WhiteLen:=-1;
  7078. WhiteLen:= WhiteLen shr 1; { logical SHR to get max sw_integer }
  7079. for i:=SelStart.Y to ey do
  7080. begin
  7081. S:=GetDisplayText(i);
  7082. LLen:=Max(LLen,Length(S));
  7083. S:=GetLineText(i);
  7084. LLen:=Max(LLen,Length(S)); {whatever is longer displayed text or actual line text }
  7085. WhiteLen:=Min(WhiteLen,Length(S));
  7086. if WhiteLen = 0 then
  7087. break; {string length is zero, no lower where to go }
  7088. k:=1;
  7089. while (k<=WhiteLen) and (S[k]=' ') do { Tab do not count in }
  7090. inc(k);
  7091. WhiteLen:=k-1;
  7092. if WhiteLen = 0 then
  7093. break; { we have done enough, no white spaces at all }
  7094. end;
  7095. if WhiteLen=(sw_integer(-1) shr 1) then
  7096. WhiteLen:=0; { eee, never can happen, but if ever then we will be safe }
  7097. {$if sizeof(sw_astring)>8}
  7098. if LLen > 252 then { if lines are shortstrings and there is no room to add 2 chars }
  7099. begin
  7100. UnLock;
  7101. MessageBox('Lines too long!', nil, mfOKButton);
  7102. exit;
  7103. end;
  7104. {$endif}
  7105. AddGroupedAction(eaCommentSel);
  7106. WasPersistentBlocks:=IsFlagSet(efPersistentBlocks);
  7107. if not WasPersistentBlocks then
  7108. SetFlags(GetFlags or efPersistentBlocks);
  7109. {selection Start and End move along}
  7110. if SelStart.X>WhiteLen then inc(SelStart.X,2);
  7111. if SelEnd.X>WhiteLen then inc(SelEnd.X,2);
  7112. { put line comment in front of every selected line }
  7113. Ind:='//';
  7114. for i:=SelStart.Y to ey do
  7115. begin
  7116. S:=GetLineText(i);
  7117. S:=copy(S,1,WhiteLen)+Ind+copy(S,WhiteLen+1,Length(S));
  7118. SetLineText(i,S);
  7119. Pos.X:=WhiteLen;Pos.Y:=i;
  7120. AddAction(eaInsertText,Pos,Pos,Ind,GetFlags);
  7121. end;
  7122. Pos:=CurPos;
  7123. { this removes selection if Shift is pressed as well }
  7124. if (CurPos.X > WhiteLen) and (SelStart.Y<=CurPos.Y) and (CurPos.Y<=ey) then
  7125. SetCurPtr(CurPos.X+2,CurPos.Y);
  7126. {after SetCurPtr return PersistentBlocks as it was before}
  7127. if not WasPersistentBlocks then
  7128. SetFlags(GetFlags and (not longword(efPersistentBlocks)));
  7129. { must be added manually here PM }
  7130. AddAction(eaMoveCursor,Pos,CurPos,'',GetFlags);
  7131. UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
  7132. DrawLines(CurPos.Y);
  7133. SetModified(true);
  7134. CloseGroupedAction(eaCommentSel);
  7135. UnLock;
  7136. end;
  7137. procedure TCustomCodeEditor.UnCommentSel;
  7138. var
  7139. ey,i : Sw_Integer;
  7140. S,Ind : Sw_AString;
  7141. Pos : Tpoint;
  7142. WasPersistentBlocks : boolean;
  7143. WhiteLen, k : Sw_Integer;
  7144. WasGroupAction : boolean;
  7145. NeedToMoveCursor:boolean;
  7146. begin
  7147. if IsReadOnly then Exit;
  7148. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  7149. Lock;
  7150. ey:=SelEnd.Y;
  7151. if SelEnd.X=0 then
  7152. dec(ey);
  7153. WasGroupAction:=false;
  7154. NeedToMoveCursor:=false;
  7155. { remove line comment from beginning of every selected line ( if there is any) }
  7156. Ind:='//';
  7157. for i:=SelStart.Y to ey do
  7158. begin
  7159. S:=GetLineText(i);
  7160. if Length(S)<2 then continue;
  7161. WhiteLen:=0;
  7162. for k:=1 to Length(S)-1 do
  7163. if not (S[k] in [' ',#9]) then
  7164. break; { white space is over }
  7165. if (S[k]<>'/') or (S[k+1]<>'/') then continue; { continue if comment not found }
  7166. WhiteLen:=k-1;
  7167. if not WasGroupAction then
  7168. begin
  7169. {add group action only if there is at least one action
  7170. because empty group action throw segment fault when do Undo }
  7171. WasGroupAction:=true;
  7172. AddGroupedAction(eaUnCommentSel);
  7173. end;
  7174. S:=copy(S,1,WhiteLen)+copy(S,WhiteLen+1+2,Length(S)); { delete line comment string '//' }
  7175. SetLineText(i,S);
  7176. Pos.X:=WhiteLen;Pos.Y:=i;
  7177. AddAction(eaDeleteText,Pos,Pos,Ind,GetFlags);
  7178. {selection Start and End move along}
  7179. if i=SelStart.Y then
  7180. if (SelStart.X>1) and (SelStart.X>WhiteLen+1) then dec(SelStart.X,2);
  7181. if i=SelEnd.Y then
  7182. if (SelEnd.X>1) and (SelEnd.X>WhiteLen+1) then dec(SelEnd.X,2);
  7183. if i=CurPos.Y then
  7184. if (CurPos.X>1) and (CurPos.X>WhiteLen+1) then NeedToMoveCursor:=true;
  7185. end;
  7186. if WasGroupAction then
  7187. begin
  7188. WasPersistentBlocks:=IsFlagSet(efPersistentBlocks);
  7189. if not WasPersistentBlocks then
  7190. SetFlags(GetFlags or efPersistentBlocks);
  7191. Pos:=CurPos;
  7192. { this removes selection if Shift is pressed as well }
  7193. if NeedToMoveCursor then
  7194. SetCurPtr(CurPos.X-2,CurPos.Y);
  7195. {after SetCurPtr return PersistentBlocks as it was before}
  7196. if not WasPersistentBlocks then
  7197. SetFlags(GetFlags and (not longword(efPersistentBlocks)));
  7198. { must be added manually here PM }
  7199. AddAction(eaMoveCursor,Pos,CurPos,'',GetFlags);
  7200. UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
  7201. DrawLines(CurPos.Y);
  7202. SetModified(true);
  7203. CloseGroupedAction(eaUnCommentSel);
  7204. end;
  7205. UnLock;
  7206. end;
  7207. procedure TCustomCodeEditor.SelectionChanged;
  7208. var Enable,CanPaste: boolean;
  7209. begin
  7210. if GetLineCount=0 then
  7211. begin
  7212. SelStart.X:=0; SelStart.Y:=0; SelEnd:=SelStart;
  7213. end
  7214. else
  7215. if SelEnd.Y>GetLineCount-1 then
  7216. if (SelEnd.Y<>GetLineCount) or (SelEnd.X<>0) then
  7217. begin
  7218. SelEnd.Y:=GetLineCount-1;
  7219. SelEnd.X:=length(GetDisplayText(SelEnd.Y));
  7220. end;
  7221. { we change the CurCommandSet, but only if we are top view }
  7222. if ((State and sfFocused)<>0) then
  7223. begin
  7224. Enable:=((SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y)) and (Clipboard<>nil);
  7225. SetCmdState(ToClipCmds,Enable and (Clipboard<>@Self));
  7226. SetCmdState(NulClipCmds,Enable);
  7227. CanPaste:=(Clipboard<>nil) and ((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
  7228. (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
  7229. SetCmdState(FromClipCmds,CanPaste and (Clipboard<>@Self));
  7230. SetCmdState(UndoCmd,(GetUndoActionCount>0));
  7231. SetCmdState(RedoCmd,(GetRedoActionCount>0));
  7232. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  7233. end;
  7234. DrawView;
  7235. end;
  7236. procedure TCustomCodeEditor.HighlightChanged;
  7237. begin
  7238. DrawView;
  7239. end;
  7240. procedure TCustomCodeEditor.SetState(AState: Word; Enable: Boolean);
  7241. procedure ShowSBar(SBar: PScrollBar);
  7242. begin
  7243. if Assigned(SBar) and (SBar^.GetState(sfVisible)=false) then
  7244. SBar^.Show;
  7245. end;
  7246. begin
  7247. inherited SetState(AState,Enable);
  7248. if AlwaysShowScrollBars then
  7249. begin
  7250. ShowSBar(HScrollBar);
  7251. ShowSBar(VScrollBar);
  7252. end;
  7253. if (AState and (sfActive+sfSelected+sfFocused))<>0 then
  7254. begin
  7255. SelectionChanged;
  7256. if ((State and sfFocused)=0) and (GetCompleteState=csOffering) then
  7257. ClearCodeCompleteWord;
  7258. end;
  7259. end;
  7260. function TCustomCodeEditor.GetPalette: PPalette;
  7261. const P: string[length(CEditor)] = CEditor;
  7262. begin
  7263. GetPalette:=@P;
  7264. end;
  7265. function TCustomCodeEditorCore.LoadFromStream(Editor: PCustomCodeEditor; Stream: PFastBufStream): boolean;
  7266. var S: sw_AString;
  7267. AllLinesComplete,LineComplete,hasCR,OK: boolean;
  7268. begin
  7269. DeleteAllLines;
  7270. ChangedLine:=-1;
  7271. AllLinesComplete:=true;
  7272. OK:=(Stream^.Status=stOK);
  7273. if eofstream(Stream) then
  7274. AddLine('')
  7275. else
  7276. begin
  7277. while OK and (eofstream(Stream)=false) and (GetLineCount<MaxLineCount) do
  7278. begin
  7279. if not UseOldBufStreamMethod then
  7280. Stream^.Readline(S,LineComplete,hasCR)
  7281. else
  7282. ReadlnFromStream(Stream,S,LineComplete,hasCR);
  7283. AllLinesComplete:=AllLinesComplete and LineComplete;
  7284. OK:=OK and (Stream^.Status=stOK);
  7285. if OK then AddLine(S);
  7286. if not LineComplete and (ChangedLine=-1) then
  7287. ChangedLine:=GetLineCount;
  7288. end;
  7289. { Do not remove the final newline if it exists PM }
  7290. if hasCR then
  7291. AddLine('');
  7292. end;
  7293. LimitsChanged;
  7294. if not AllLinesComplete then
  7295. SetModified(true);
  7296. if (GetLineCount=MaxLineCount) and not eofstream(stream) then
  7297. EditorDialog(edTooManyLines,nil);
  7298. LoadFromStream:=OK;
  7299. end;
  7300. function TCustomCodeEditorCore.SaveAreaToStream(Editor: PCustomCodeEditor; Stream: PStream; StartP,EndP: TPoint): boolean;
  7301. var S: sw_astring;
  7302. OK: boolean;
  7303. Line: Sw_integer;
  7304. begin
  7305. if EndP.X=0 then
  7306. begin
  7307. if EndP.Y>0 then
  7308. begin
  7309. EndP.X:=length(GetDisplayText(EndP.Y));
  7310. end
  7311. else
  7312. EndP.X:=0;
  7313. end
  7314. else
  7315. Dec(EndP.X);
  7316. OK:=(Stream^.Status=stOK); Line:=StartP.Y;
  7317. while OK and (Line<=EndP.Y) and (Line<GetLineCount) do
  7318. begin
  7319. S:=GetLineText(Line);
  7320. { Remove all trailing spaces PM }
  7321. if not Editor^.IsFlagSet(efKeepTrailingSpaces) then
  7322. s:=RTrim(S,False); // removes trailing #0 too
  7323. { if FlagSet(efUseTabCharacters) then
  7324. S:=CompressUsingTabs(S,TabSize);
  7325. }
  7326. if Line=EndP.Y then S:=copy(S,1,LinePosToCharIdx(Line,EndP.X));
  7327. if Line=StartP.Y then S:=copy(S,LinePosToCharIdx(Line,StartP.X),Length(S));
  7328. Stream^.Write(S[1],length(S));
  7329. if Line<EndP.Y then
  7330. Stream^.Write(EOL[1],length(EOL));
  7331. Inc(Line);
  7332. OK:=OK and (Stream^.Status=stOK);
  7333. end;
  7334. SaveAreaToStream:=OK;
  7335. end;
  7336. constructor TEditorAction.init(act:byte; StartP,EndP:TPoint;Txt:Sw_AString;AFlags : longint);
  7337. begin
  7338. Action:=act;
  7339. StartPos:=StartP;
  7340. EndPos:=EndP;
  7341. SetText(Txt);
  7342. ActionCount:=0;
  7343. Flags:=AFlags;
  7344. TimeStamp:=Now;
  7345. IsGrouped:=false;
  7346. end;
  7347. constructor TEditorAction.init_group(act:byte);
  7348. begin
  7349. Action:=act;
  7350. ActionCount:=0;
  7351. Flags:=0;
  7352. IsGrouped:=true;
  7353. end;
  7354. function TEditorAction.Is_grouped_action : boolean;
  7355. begin
  7356. Is_grouped_action:=IsGrouped;
  7357. end;
  7358. function TEditorAction.GetText : sw_astring;
  7359. var st : string;
  7360. begin
  7361. {$if sizeof(sw_astring)>8}
  7362. GetText:=GetStr(Text);
  7363. {$else}
  7364. GetText:=Text;
  7365. {$endif}
  7366. end;
  7367. procedure TEditorAction.SetText(AText : sw_astring);
  7368. var st : string;
  7369. begin
  7370. {$if sizeof(sw_astring)>8}
  7371. SetStr(Text,AText);
  7372. {$else}
  7373. Text:=AText;
  7374. {$endif}
  7375. end;
  7376. destructor TEditorAction.done;
  7377. begin
  7378. {$if sizeof(sw_astring)>8}
  7379. if assigned(Text) then
  7380. DisposeStr(Text);
  7381. Text:=nil;
  7382. {$else}
  7383. Text:='';
  7384. {$endif}
  7385. inherited done;
  7386. end;
  7387. function TEditorActionCollection.At(Idx : sw_integer) : PEditorAction;
  7388. begin
  7389. At:=PEditorAction(Inherited At(Idx));
  7390. end;
  7391. procedure TEditorInputLine.HandleEvent(var Event : TEvent);
  7392. var
  7393. s : sw_astring;
  7394. st : string; {need to be shortstring for InputLine}
  7395. i : longint;
  7396. begin
  7397. If (Event.What=evKeyDown) then
  7398. begin
  7399. if (Event.KeyCode=kbRight) and
  7400. (CurPos = Length(Data^)) and
  7401. Assigned(FindReplaceEditor) then
  7402. Begin
  7403. s:=FindReplaceEditor^.GetDisplayText(FindReplaceEditor^.CurPos.Y);
  7404. i:=Min(FindReplaceEditor^.CurPos.X+1,length(s));
  7405. {finds beginning of word}
  7406. if i>0 then
  7407. while s[i] in ['a'..'z','A'..'Z','0'..'9','_'] do
  7408. begin
  7409. dec(i);
  7410. if i=0 then break;
  7411. end;
  7412. inc(i);
  7413. {step out of white space}
  7414. if i<length(s) then
  7415. while (s[i] in [' ']) do
  7416. begin
  7417. inc(i);
  7418. if i=length(s) then break;
  7419. end;
  7420. st:=Copy(s,i-length(Data^),length(s)-(i-length(Data^))+1);
  7421. if length(Data^)=0 then
  7422. i:=1 {if input line is empty then start from first character of word if any}
  7423. else
  7424. i:=pos(Data^,st);
  7425. if (i>0) and (length(st)>=i+length(Data^)) then
  7426. begin
  7427. st:=Data^+st[i+length(Data^)];
  7428. If not assigned(validator) or
  7429. Validator^.IsValidInput(st,False) then
  7430. Begin
  7431. Event.CharCode:=st[length(st)];
  7432. Event.Scancode:=0;
  7433. Inherited HandleEvent(Event);
  7434. End;
  7435. end;
  7436. ClearEvent(Event);
  7437. End
  7438. else if ((Event.KeyCode=kbShiftIns) or (Event.KeyCode=paste_key)) and
  7439. Assigned(Clipboard) and (Clipboard^.ValidBlock) then
  7440. { paste from clipboard }
  7441. begin
  7442. i:=Clipboard^.SelStart.Y;
  7443. s:=Clipboard^.GetDisplayText(i);
  7444. i:=Clipboard^.SelStart.X;
  7445. if i>0 then
  7446. s:=copy(s,i+1,length(s));
  7447. if (Clipboard^.SelStart.Y=Clipboard^.SelEnd.Y) then
  7448. begin
  7449. i:=Clipboard^.SelEnd.X-i;
  7450. s:=copy(s,1,i);
  7451. end;
  7452. for i:=1 to length(s) do
  7453. begin
  7454. st:=Data^+s[i];
  7455. If not assigned(validator) or
  7456. Validator^.IsValidInput(st,False) then
  7457. Begin
  7458. Event.What:=evKeyDown;
  7459. Event.CharCode:=s[i];
  7460. Event.Scancode:=0;
  7461. Inherited HandleEvent(Event);
  7462. End;
  7463. end;
  7464. ClearEvent(Event);
  7465. end
  7466. else if ((Event.KeyCode=kbCtrlIns) or (Event.KeyCode=copy_key)) and
  7467. Assigned(Clipboard) then
  7468. { Copy to clipboard }
  7469. begin
  7470. s:=GetStr(Data);
  7471. s:=copy(s,selstart+1,selend-selstart);
  7472. Clipboard^.SelStart:=Clipboard^.CurPos;
  7473. Clipboard^.InsertText(s);
  7474. Clipboard^.SelEnd:=Clipboard^.CurPos;
  7475. ClearEvent(Event);
  7476. end
  7477. else if ((Event.KeyCode=kbShiftDel) or (Event.KeyCode=cut_key)) and
  7478. Assigned(Clipboard) then
  7479. { Cut to clipboard }
  7480. begin
  7481. s:=GetStr(Data);
  7482. s:=copy(s,selstart+1,selend-selstart);
  7483. Clipboard^.SelStart:=Clipboard^.CurPos;
  7484. Clipboard^.InsertText(s);
  7485. Clipboard^.SelEnd:=Clipboard^.CurPos;
  7486. { now remove the selected part }
  7487. Event.keyCode:=kbDel;
  7488. inherited HandleEvent(Event);
  7489. ClearEvent(Event);
  7490. end
  7491. else if ((Event.KeyCode=kbCtrlDel)) then
  7492. { Cut & discard }
  7493. begin
  7494. { now remove the selected part }
  7495. Event.keyCode:=kbDel;
  7496. inherited HandleEvent(Event);
  7497. ClearEvent(Event);
  7498. end
  7499. else
  7500. Inherited HandleEvent(Event);
  7501. End
  7502. else
  7503. Inherited HandleEvent(Event);
  7504. st:=getstr(data);
  7505. Message(Owner,evBroadCast,cmInputLineLen,pointer(Length(st)));
  7506. end;
  7507. constructor TFPFileInputLine.Init(var Bounds: TRect; AMaxLen: Sw_Integer);
  7508. begin
  7509. inherited Init(Bounds, AMaxLen);
  7510. end;
  7511. procedure TFPFileInputLine.HandleEvent(var Event: TEvent);
  7512. var s : sw_astring;
  7513. i : sw_integer;
  7514. st: string;
  7515. begin
  7516. If (Event.What=evKeyDown) then
  7517. begin
  7518. if ((Event.KeyCode=kbShiftIns) or (Event.KeyCode=paste_key)) and
  7519. Assigned(weditor.Clipboard) and (weditor.Clipboard^.ValidBlock) then
  7520. { paste from clipboard }
  7521. begin
  7522. i:=Clipboard^.SelStart.Y;
  7523. s:=Clipboard^.GetDisplayText(i);
  7524. i:=Clipboard^.SelStart.X;
  7525. if i>0 then
  7526. s:=copy(s,i+1,length(s));
  7527. if (Clipboard^.SelStart.Y=Clipboard^.SelEnd.Y) then
  7528. begin
  7529. i:=Clipboard^.SelEnd.X-i;
  7530. s:=copy(s,1,i);
  7531. end;
  7532. for i:=1 to length(s) do
  7533. begin
  7534. st:=Data^+s[i];
  7535. If not assigned(validator) or
  7536. Validator^.IsValidInput(st,False) then
  7537. Begin
  7538. Event.What:=evKeyDown;
  7539. Event.CharCode:=s[i];
  7540. Event.Scancode:=0;
  7541. Inherited HandleEvent(Event);
  7542. End;
  7543. end;
  7544. ClearEvent(Event);
  7545. end
  7546. else if ((Event.KeyCode=kbCtrlIns) or (Event.KeyCode=copy_key)) and
  7547. Assigned(Clipboard) then
  7548. { Copy to clipboard }
  7549. begin
  7550. s:=GetStr(Data);
  7551. s:=copy(s,selstart+1,selend-selstart);
  7552. Clipboard^.SelStart:=Clipboard^.CurPos;
  7553. Clipboard^.InsertText(s);
  7554. Clipboard^.SelEnd:=Clipboard^.CurPos;
  7555. ClearEvent(Event);
  7556. end
  7557. else if ((Event.KeyCode=kbShiftDel) or (Event.KeyCode=cut_key)) and
  7558. Assigned(Clipboard) then
  7559. { Cut to clipboard }
  7560. begin
  7561. s:=GetStr(Data);
  7562. s:=copy(s,selstart+1,selend-selstart);
  7563. Clipboard^.SelStart:=Clipboard^.CurPos;
  7564. Clipboard^.InsertText(s);
  7565. Clipboard^.SelEnd:=Clipboard^.CurPos;
  7566. { now remove the selected part }
  7567. Event.keyCode:=kbDel;
  7568. inherited HandleEvent(Event);
  7569. ClearEvent(Event);
  7570. end
  7571. else if ((Event.KeyCode=kbCtrlDel)) then
  7572. { Cut & discard }
  7573. begin
  7574. { now remove the selected part }
  7575. Event.keyCode:=kbDel;
  7576. inherited HandleEvent(Event);
  7577. ClearEvent(Event);
  7578. end
  7579. else
  7580. Inherited HandleEvent(Event);
  7581. End
  7582. else
  7583. Inherited HandleEvent(Event);
  7584. //st:=getstr(data);
  7585. //Message(Owner,evBroadCast,cmInputLineLen,pointer(Length(st)));
  7586. end;
  7587. constructor TFPFileDialog.Init(AWildCard: TWildStr; const ATitle,
  7588. InputName: String; AOptions: Word; HistoryId: Byte);
  7589. var R: TRect;
  7590. DInput : PFPFileInputLine;
  7591. Control : PView;
  7592. History : PHistory;
  7593. S : String;
  7594. begin
  7595. inherited init(AWildCard,ATitle,InputName,AOptions,HistoryId);
  7596. FileName^.getData(S);
  7597. FileName^.GetBounds(R);
  7598. DInput := New(PFPFileInputLine, Init(R, 79{FileNameLen+4}));
  7599. DInput^.SetData(S);
  7600. DInput^.GrowMode:=FileName^.GrowMode;
  7601. InsertBefore(DInput,FileName); {insert before to preserve order as it was}
  7602. Delete(FileName);
  7603. Dispose(FileName,done);
  7604. FileName:=DInput;
  7605. FileHistory^.Link:=DInput;
  7606. {resize}
  7607. if Desktop^.Size.Y > 26 then
  7608. GrowTo(Size.X,Desktop^.Size.Y-6);
  7609. if Desktop^.Size.X > 70 then
  7610. GrowTo(Min(Desktop^.Size.X-(70-Size.X),102),Size.Y);
  7611. FileList^.NumCols:= Max((FileList^.Size.X-(FileList^.Size.X div 14)) div 14,2);
  7612. { Adjust scrollbar step and page step }
  7613. FileList^.SetRange(FileList^.Range); {set again for scrollbar min max values}
  7614. {set focus on the new input line}
  7615. DInput^.Focus;
  7616. end;
  7617. procedure TSearchHelperDialog.HandleEvent(var Event : TEvent);
  7618. begin
  7619. case Event.What of
  7620. evBroadcast :
  7621. case Event.Command of
  7622. cminputlinelen : begin
  7623. if PtrInt(Event.InfoPtr)=0 then
  7624. okbutton^.DisableCommands([cmok])
  7625. else
  7626. okbutton^.EnableCommands([cmok]);
  7627. clearevent(event);
  7628. end;
  7629. end;
  7630. end;
  7631. inherited HandleEvent(Event);
  7632. end;
  7633. function CreateFindDialog: PDialog;
  7634. var R,R1,R2: TRect;
  7635. D: PSearchHelperDialog;
  7636. IL1: PEditorInputLine;
  7637. Control : PView;
  7638. CB1: PCheckBoxes;
  7639. RB1,RB2,RB3: PRadioButtons;
  7640. but : PButton;
  7641. begin
  7642. R.Assign(0,0,56,15);
  7643. New(D, Init(R, dialog_find));
  7644. with D^ do
  7645. begin
  7646. Options:=Options or ofCentered;
  7647. GetExtent(R); R.Grow(-3,-2);
  7648. R1.Copy(R); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  7649. R2.Copy(R); R2.B.X:=R2.B.X-3;R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  7650. New(IL1, Init(R2, FindStrSize));
  7651. IL1^.Data^:=FindStr;
  7652. Insert(IL1);
  7653. Insert(New(PLabel, Init(R1, label_find_texttofind, IL1)));
  7654. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  7655. Control := New(PHistory, Init(R1, IL1, TextFindId));
  7656. Insert(Control);
  7657. R1.Copy(R); Inc(R1.A.Y,2); R1.B.Y:=R1.A.Y+1; R1.B.X:=R1.A.X+(R1.B.X-R1.A.X) div 2-1;
  7658. R2.Copy(R1); R2.Move(0,1);
  7659. R2.B.Y:=R2.A.Y+{$ifdef TEST_REGEXP}3{$else}2{$endif};
  7660. New(CB1, Init(R2,
  7661. NewSItem(label_find_casesensitive,
  7662. NewSItem(label_find_wholewordsonly,
  7663. {$ifdef TEST_REGEXP}
  7664. NewSItem(label_find_useregexp,
  7665. {$endif TEST_REGEXP}
  7666. nil)))){$ifdef TEST_REGEXP}){$endif TEST_REGEXP};
  7667. Insert(CB1);
  7668. Insert(New(PLabel, Init(R1, label_find_options, CB1)));
  7669. R1.Copy(R); Inc(R1.A.Y,2); R1.B.Y:=R1.A.Y+1; R1.A.X:=R1.B.X-(R1.B.X-R1.A.X) div 2+1;
  7670. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7671. New(RB1, Init(R2,
  7672. NewSItem(label_find_forward,
  7673. NewSItem(label_find_backward,
  7674. nil))));
  7675. Insert(RB1);
  7676. Insert(New(PLabel, Init(R1, label_find_direction, RB1)));
  7677. R1.Copy(R); Inc(R1.A.Y,6); R1.B.Y:=R1.A.Y+1; R1.B.X:=R1.A.X+(R1.B.X-R1.A.X) div 2-1;
  7678. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7679. New(RB2, Init(R2,
  7680. NewSItem(label_find_global,
  7681. NewSItem(label_find_selectedtext,
  7682. nil))));
  7683. Insert(RB2);
  7684. Insert(New(PLabel, Init(R1, label_find_scope, RB2)));
  7685. R1.Copy(R); Inc(R1.A.Y,6); R1.B.Y:=R1.A.Y+1; R1.A.X:=R1.B.X-(R1.B.X-R1.A.X) div 2+1;
  7686. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7687. New(RB3, Init(R2,
  7688. NewSItem(label_find_fromcursor,
  7689. NewSItem(label_find_entirescope,
  7690. nil))));
  7691. Insert(RB3);
  7692. Insert(New(PLabel, Init(R1, label_find_origin, RB3)));
  7693. GetExtent(R); R.Grow(-13,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10;
  7694. Okbutton:=New(PButton, Init(R, btn_OK, cmOK, bfDefault));
  7695. Insert(OkButton);
  7696. R.Move(19,0);
  7697. Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
  7698. end;
  7699. IL1^.Select;
  7700. CreateFindDialog := D;
  7701. end;
  7702. function CreateReplaceDialog: PDialog;
  7703. var R,R1,R2: TRect;
  7704. D: PDialog;
  7705. Control : PView;
  7706. IL1: PEditorInputLine;
  7707. IL2: PEditorInputLine;
  7708. CB1: PCheckBoxes;
  7709. RB1,RB2,RB3: PRadioButtons;
  7710. begin
  7711. R.Assign(0,0,56,18);
  7712. New(D, Init(R, dialog_replace));
  7713. with D^ do
  7714. begin
  7715. Options:=Options or ofCentered;
  7716. GetExtent(R); R.Grow(-3,-2);
  7717. R1.Copy(R); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  7718. R2.Copy(R); R2.B.X:=R2.B.X-3;R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  7719. New(IL1, Init(R2, FindStrSize));
  7720. IL1^.Data^:=FindStr;
  7721. Insert(IL1);
  7722. Insert(New(PLabel, Init(R1, label_replace_texttofind, IL1)));
  7723. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  7724. Control := New(PHistory, Init(R1, IL1, TextFindId));
  7725. Insert(Control);
  7726. R1.Copy(R); R1.Move(0,2); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  7727. R2.Copy(R); R2.Move(0,2);R2.B.X:=R2.B.X-3;
  7728. R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  7729. New(IL2, Init(R2, FindStrSize));
  7730. IL2^.Data^:=ReplaceStr;
  7731. Insert(IL2);
  7732. Insert(New(PLabel, Init(R1, label_replace_newtext, IL2)));
  7733. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  7734. Control := New(PHistory, Init(R1, IL2, TextReplaceId));
  7735. Insert(Control);
  7736. R1.Copy(R); Inc(R1.A.Y,4); R1.B.Y:=R1.A.Y+1; R1.B.X:=R1.A.X+(R1.B.X-R1.A.X) div 2-1;
  7737. R2.Copy(R1); R2.Move(0,1);
  7738. R2.B.Y:=R2.A.Y+{$ifdef TEST_REGEXP}4{$else}3{$endif};
  7739. New(CB1, Init(R2,
  7740. NewSItem(label_replace_casesensitive,
  7741. NewSItem(label_replace_wholewordsonly,
  7742. NewSItem(label_replace_promptonreplace,
  7743. {$ifdef TEST_REGEXP}
  7744. NewSItem(label_find_useregexp,
  7745. {$endif TEST_REGEXP}
  7746. nil))))){$ifdef TEST_REGEXP}){$endif TEST_REGEXP};
  7747. Insert(CB1);
  7748. Insert(New(PLabel, Init(R1, label_replace_options, CB1)));
  7749. R1.Copy(R); Inc(R1.A.Y,4); R1.B.Y:=R1.A.Y+1; R1.A.X:=R1.B.X-(R1.B.X-R1.A.X) div 2+1;
  7750. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7751. New(RB1, Init(R2,
  7752. NewSItem(label_replace_forward,
  7753. NewSItem(label_replace_backward,
  7754. nil))));
  7755. Insert(RB1);
  7756. Insert(New(PLabel, Init(R1, label_replace_direction, RB1)));
  7757. R1.Copy(R); Inc(R1.A.Y,9); R1.B.Y:=R1.A.Y+1; R1.B.X:=R1.A.X+(R1.B.X-R1.A.X) div 2-1;
  7758. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7759. New(RB2, Init(R2,
  7760. NewSItem(label_replace_global,
  7761. NewSItem(label_replace_selectedtext,
  7762. nil))));
  7763. Insert(RB2);
  7764. Insert(New(PLabel, Init(R1, label_replace_scope, RB2)));
  7765. R1.Copy(R); Inc(R1.A.Y,9); R1.B.Y:=R1.A.Y+1; R1.A.X:=R1.B.X-(R1.B.X-R1.A.X) div 2+1;
  7766. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7767. New(RB3, Init(R2,
  7768. NewSItem(label_replace_fromcursor,
  7769. NewSItem(label_replace_entirescope,
  7770. nil))));
  7771. Insert(RB3);
  7772. Insert(New(PLabel, Init(R1, label_replace_origin, RB3)));
  7773. GetExtent(R); R.Grow(-13,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10; R.Move(-10,0);
  7774. Insert(New(PButton, Init(R, btn_OK, cmOK, bfDefault)));
  7775. R.Move(11,0); R.B.X:=R.A.X+14;
  7776. Insert(New(PButton, Init(R, btn_replace_changeall, cmYes, bfNormal)));
  7777. R.Move(15,0); R.B.X:=R.A.X+10;
  7778. Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
  7779. end;
  7780. IL1^.Select;
  7781. CreateReplaceDialog := D;
  7782. end;
  7783. function CreateGotoLineDialog(Info: pointer): PDialog;
  7784. var D: PDialog;
  7785. R,R1,R2: TRect;
  7786. Control : PView;
  7787. IL: PEditorInputLine;
  7788. begin
  7789. R.Assign(0,0,40,7);
  7790. New(D, Init(R, dialog_gotoline));
  7791. with D^ do
  7792. begin
  7793. Options:=Options or ofCentered;
  7794. GetExtent(R); R.Grow(-3,-2); R.B.Y:=R.A.Y+1;
  7795. R1.Copy(R); R1.B.X:=27; R2.Copy(R);
  7796. R2.B.X:=R2.B.X-3;R2.A.X:=27;
  7797. New(IL, Init(R2,5));
  7798. with TGotoLineDialogRec(Info^) do
  7799. IL^.SetValidator(New(PRangeValidator, Init(1, Lines)));
  7800. Insert(IL);
  7801. Insert(New(PLabel, Init(R1, label_gotoline_linenumber, IL)));
  7802. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  7803. Control := New(PHistory, Init(R1, IL, GotoId));
  7804. Insert(Control);
  7805. GetExtent(R); R.Grow(-8,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10;
  7806. Insert(New(PButton, Init(R, btn_OK, cmOK, bfDefault)));
  7807. R.Move(15,0);
  7808. Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
  7809. end;
  7810. IL^.Select;
  7811. CreateGotoLineDialog:=D;
  7812. end;
  7813. function StdEditorDialog(Dialog: Integer; Info: Pointer): Word;
  7814. var
  7815. R: TRect;
  7816. T: TPoint;
  7817. Re: word;
  7818. Name: string;
  7819. DriveNumber : byte;
  7820. StoreDir,StoreDir2 : DirStr;
  7821. Title,DefExt: string;
  7822. AskOW: boolean;
  7823. begin
  7824. case Dialog of
  7825. edOutOfMemory:
  7826. StdEditorDialog := AdvMessageBox(msg_notenoughmemoryforthisoperation,
  7827. nil, mfInsertInApp+ mfError + mfOkButton);
  7828. edReadError:
  7829. StdEditorDialog := AdvMessageBox(msg_errorreadingfile,
  7830. @Info, mfInsertInApp+ mfError + mfOkButton);
  7831. edWriteError:
  7832. StdEditorDialog := AdvMessageBox(msg_errorwritingfile,
  7833. @Info, mfInsertInApp+ mfError + mfOkButton);
  7834. edSaveError:
  7835. StdEditorDialog := AdvMessageBox(msg_errorsavingfile,
  7836. @Info, mfInsertInApp+ mfError + mfOkButton);
  7837. edCreateError:
  7838. StdEditorDialog := AdvMessageBox(msg_errorcreatingfile,
  7839. @Info, mfInsertInApp+ mfError + mfOkButton);
  7840. edSaveModify:
  7841. StdEditorDialog := AdvMessageBox(msg_filehasbeenmodifiedsave,
  7842. @Info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7843. edSaveUntitled:
  7844. StdEditorDialog := AdvMessageBox(msg_saveuntitledfile,
  7845. nil, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7846. edChangedOnloading:
  7847. StdEditorDialog := AdvMessageBox(msg_filehadtoolonglines,
  7848. Info, mfInsertInApp+ mfOKButton + mfInformation);
  7849. edFileOnDiskChanged:
  7850. StdEditorDialog := AdvMessageBox(msg_filewasmodified,
  7851. @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7852. edReloadDiskmodifiedFile:
  7853. StdEditorDialog := AdvMessageBox(msg_reloaddiskmodifiedfile,
  7854. @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7855. edReloadDiskAndIDEModifiedFile:
  7856. StdEditorDialog := AdvMessageBox(msg_reloaddiskandidemodifiedfile,
  7857. @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7858. edSaveAs,edWriteBlock,edReadBlock:
  7859. begin
  7860. Name:=PString(Info)^;
  7861. GetDir(0,StoreDir);
  7862. DriveNumber:=0;
  7863. if (Length(FileDir)>1) and (FileDir[2]=':') then
  7864. begin
  7865. { does not assume that lowercase are greater then uppercase ! }
  7866. if (FileDir[1]>='a') and (FileDir[1]<='z') then
  7867. DriveNumber:=Ord(FileDir[1])-ord('a')+1
  7868. else
  7869. DriveNumber:=Ord(FileDir[1])-ord('A')+1;
  7870. GetDir(DriveNumber,StoreDir2);
  7871. {$I-}
  7872. ChDir(Copy(FileDir,1,2));
  7873. EatIO;
  7874. {$I+}
  7875. end;
  7876. if FileDir<>'' then
  7877. begin
  7878. {$I-}
  7879. ChDir(TrimEndSlash(FileDir));
  7880. EatIO;
  7881. {$I+}
  7882. end;
  7883. case Dialog of
  7884. edSaveAs :
  7885. begin
  7886. Title:=dialog_savefileas;
  7887. DefExt:='*'+DefaultSaveExt;
  7888. end;
  7889. edWriteBlock :
  7890. begin
  7891. Title:=dialog_writeblocktofile;
  7892. DefExt:='*.*';
  7893. end;
  7894. edReadBlock :
  7895. begin
  7896. Title:=dialog_readblockfromfile;
  7897. DefExt:='*.*';
  7898. end;
  7899. else begin Title:='???'; DefExt:=''; end;
  7900. end;
  7901. Re:=Application^.ExecuteDialog(New(PFPFileDialog, Init(DefExt,
  7902. Title, label_name, fdOkButton, FileId)), @Name);
  7903. case Dialog of
  7904. edSaveAs :
  7905. begin
  7906. if ExtOf(Name)='' then
  7907. Name:=Name+DefaultSaveExt;
  7908. AskOW:=(Name<>PString(Info)^);
  7909. end;
  7910. edWriteBlock :
  7911. begin
  7912. if ExtOf(Name)='' then
  7913. Name:=Name+DefaultSaveExt;
  7914. AskOW:=true;
  7915. end;
  7916. edReadBlock : AskOW:=false;
  7917. else AskOW:=true;
  7918. end;
  7919. if (Re<>cmCancel) and AskOW then
  7920. begin
  7921. FileDir:=DirOf(FExpand(Name));
  7922. if ExistsFile(Name) then
  7923. if EditorDialog(edReplaceFile,@Name)<>cmYes then
  7924. Re:=cmCancel;
  7925. end;
  7926. if DriveNumber<>0 then
  7927. ChDir(StoreDir2);
  7928. if StoreDir<>'' then
  7929. ChDir(TrimEndSlash(StoreDir));
  7930. if Re<>cmCancel then
  7931. PString(Info)^:=Name;
  7932. StdEditorDialog := Re;
  7933. end;
  7934. edGotoLine:
  7935. StdEditorDialog :=
  7936. Application^.ExecuteDialog(CreateGotoLineDialog(Info), Info);
  7937. edFind:
  7938. StdEditorDialog :=
  7939. Application^.ExecuteDialog(CreateFindDialog, Info);
  7940. edSearchFailed:
  7941. StdEditorDialog := AdvMessageBox(msg_searchstringnotfound,
  7942. nil, mfInsertInApp+ mfError + mfOkButton);
  7943. edReplace:
  7944. StdEditorDialog :=
  7945. Application^.ExecuteDialog(CreateReplaceDialog, Info);
  7946. edReplacePrompt:
  7947. begin
  7948. { Avoid placing the dialog on the same line as the cursor }
  7949. R.Assign(0, 1, 40, 8);
  7950. R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  7951. Desktop^.MakeGlobal(R.B, T);
  7952. Inc(T.Y);
  7953. if PPoint(Info)^.Y <= T.Y then
  7954. R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  7955. StdEditorDialog := AdvMessageBoxRect(R, msg_replacethisoccourence,
  7956. nil, mfInsertInApp+ mfYesNoCancel + mfInformation);
  7957. end;
  7958. edReplaceFile :
  7959. StdEditorDialog :=
  7960. AdvMessageBox(msg_fileexistsoverwrite,@Info,mfInsertInApp+mfConfirmation+
  7961. mfYesButton+mfNoButton);
  7962. end;
  7963. end;
  7964. procedure RegisterWEditor;
  7965. begin
  7966. {$ifndef NOOBJREG}
  7967. {$endif}
  7968. end;
  7969. END.