weditor.pas 225 KB

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