weditor.pas 224 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043
  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:=0
  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. end;
  2406. if MatchedSymbol and (InComment=false) then
  2407. SymbolConcat:='';
  2408. LastCC:=CC;
  2409. end;
  2410. end;
  2411. var Line,NextLine,PrevLine{,OldLine}: PCustomLine;
  2412. PrevLI,LI,nextLI: PEditorLineInfo;
  2413. begin
  2414. if (not Editor^.IsFlagSet(efSyntaxHighlight)) or (FromLine>=GetLineCount) then
  2415. begin
  2416. SetLineFormat(Editor,FromLine,'');
  2417. DoUpdateAttrs:=GetLineCount;
  2418. {$ifdef TEST_PARTIAL_SYNTAX}
  2419. LastSyntaxedLine:=GetLineCount;
  2420. if not SyntaxComplete then
  2421. begin
  2422. SyntaxComplete:=true;
  2423. DoSyntaxStateChanged;
  2424. end;
  2425. (* { no Idle necessary }
  2426. EventMask:=EventMask and not evIdle;*)
  2427. {$endif TEST_PARTIAL_SYNTAX}
  2428. Editor^.SyntaxStateChanged;
  2429. Exit;
  2430. end;
  2431. {$ifdef TEST_PARTIAL_SYNTAX}
  2432. If Editor^.IsFlagSet(efSyntaxHighlight) and (LastSyntaxedLine<FromLine)
  2433. and (FromLine<GetLineCount) then
  2434. CurLineNr:=LastSyntaxedLine
  2435. else
  2436. {$endif TEST_PARTIAL_SYNTAX}
  2437. CurLineNr:=FromLine;
  2438. if CurLineNr>0 then
  2439. PrevLine:=GetLine(CurLineNr-1)
  2440. else
  2441. PrevLine:=nil;
  2442. CommentStartY:=CurLineNr-1; { use in detection for false positive commment: (*) }
  2443. repeat
  2444. Line:=GetLine(CurLineNr);
  2445. if Assigned(PrevLine) then PrevLI:=PrevLine^.GetEditorInfo(Editor) else PrevLI:=nil;
  2446. if Assigned(Line) then LI:=Line^.GetEditorInfo(Editor) else LI:=nil;
  2447. InSingleLineComment:=false;
  2448. if PrevLI<>nil then
  2449. begin
  2450. InAsm:=PrevLI^.EndsWithAsm;
  2451. InComment:=PrevLI^.EndsWithComment and not PrevLI^.EndsInSingleLineComment;
  2452. CurrentCommentType:=PrevLI^.EndCommentType;
  2453. CurrentCommentDepth:=PrevLI^.EndCommentDepth;
  2454. NestedComments:=(PrevLI^.EndNestedComments and 1)=1;
  2455. LookForNestedComments:=(PrevLI^.EndNestedComments and 2)=2;
  2456. InDirective:=PrevLI^.EndsWithDirective;
  2457. end
  2458. else
  2459. begin
  2460. InAsm:=false;
  2461. InComment:=false;
  2462. CurrentCommentType:=0;
  2463. CurrentCommentDepth:=0;
  2464. InDirective:=false;
  2465. NestedComments:=false;
  2466. LookForNestedComments:=false;
  2467. end;
  2468. { OldLine:=Line;}
  2469. if (not Editor^.IsFlagSet(efKeepLineAttr)) then
  2470. begin
  2471. LI^.BeginsWithAsm:=InAsm;
  2472. LI^.BeginsWithComment:=InComment;
  2473. LI^.BeginsWithDirective:=InDirective;
  2474. LI^.BeginCommentType:=CurrentCommentType;
  2475. LI^.BeginCommentDepth:=CurrentCommentDepth;
  2476. LI^.BeginNestedComments:=byte(NestedComments) and 1;
  2477. LI^.BeginNestedComments:=LI^.BeginNestedComments or ((byte(LookForNestedComments)and 1) shl 1);
  2478. end
  2479. else
  2480. begin
  2481. InAsm:=LI^.BeginsWithAsm;
  2482. InComment:=LI^.BeginsWithComment;
  2483. InDirective:=LI^.BeginsWithDirective;
  2484. CurrentCommentType:=LI^.BeginCommentType;
  2485. CurrentCommentDepth:=LI^.BeginCommentDepth;
  2486. NestedComments:=(LI^.BeginNestedComments and 1)=1;
  2487. LookForNestedComments:=(LI^.BeginNestedComments and 2)=2;
  2488. end;
  2489. LineText:=GetLineText(CurLineNr);
  2490. Format:=CharStr(chr(coTextColor),length(LineText));
  2491. LastCC:=ccWhiteSpace;
  2492. ClassStart:=1;
  2493. SymbolConcat:='';
  2494. InString:=false;
  2495. if LineText<>'' then
  2496. begin
  2497. for X:=1 to length(LineText) do
  2498. ProcessChar(LineText[X]);
  2499. Inc(X);
  2500. ProcessChar(' ');
  2501. end;
  2502. SetLineFormat(Editor,CurLineNr,Format);
  2503. LI^.EndsWithAsm:=InAsm;
  2504. LI^.EndsWithComment:=InComment;
  2505. LI^.EndsInSingleLineComment:=InSingleLineComment;
  2506. LI^.EndNestedComments:=byte(NestedComments) and 1;
  2507. LI^.EndNestedComments:=LI^.EndNestedComments or ((byte(LookForNestedComments)and 1) shl 1);
  2508. LI^.EndCommentDepth:=CurrentCommentDepth;
  2509. LI^.EndCommentType:=CurrentCommentType;
  2510. LI^.EndsWithDirective:=InDirective;
  2511. Inc(CurLineNr);
  2512. if CurLineNr>=GetLineCount then
  2513. Break;
  2514. NextLine:=GetLine(CurLineNr);
  2515. if Assigned(NextLine) then NextLI:=NextLine^.GetEditorInfo(Editor) else NextLI:=nil;
  2516. if ((Attrs and attrForceFull)=0) then
  2517. if (* Why should we go
  2518. (InAsm=false) and (NextLI^.BeginsWithAsm=false) and
  2519. (InComment=false) and (NextLI^.BeginsWithComment=false) and
  2520. (InDirective=false) and (NextLI^.BeginsWithDirective=false) and
  2521. { OldLine = Line so this is nonsense}
  2522. (PrevLI^.EndsWithComment=LI^.EndsWithComment) and
  2523. (PrevLI^.EndsWithAsm=LI^.EndsWithAsm) and
  2524. (PrevLI^.EndsWithDirective=LI^.EndsWithDirective) and *)
  2525. {$ifdef TEST_PARTIAL_SYNTAX}
  2526. (CurLineNr>FromLine) and
  2527. {$endif TEST_PARTIAL_SYNTAX}
  2528. (NextLI^.BeginsWithAsm=LI^.EndsWithAsm) and
  2529. (NextLI^.BeginsWithComment=LI^.EndsWithComment) and
  2530. (NextLI^.BeginsWithDirective=LI^.EndsWithDirective) and
  2531. (NextLI^.BeginCommentType=LI^.EndCommentType) and
  2532. (NextLI^.BeginNestedComments=LI^.EndNestedComments) and
  2533. (NextLI^.BeginCommentDepth=LI^.EndCommentDepth) and
  2534. (Length(NextLI^.GetFormat)>0) then
  2535. Break;
  2536. {$ifdef TEST_PARTIAL_SYNTAX}
  2537. if (CurLineNr<GetLineCount) and
  2538. (CurLineNr>FromLine) and
  2539. ((Attrs and attrForceFull)=0) and
  2540. (CurLineNr>GetLastVisibleLine) then
  2541. begin
  2542. If SyntaxComplete then
  2543. begin
  2544. SyntaxComplete:=false;
  2545. DoSyntaxStateChanged;
  2546. end;
  2547. LastSyntaxedLine:=CurLineNr-1;
  2548. break;
  2549. end;
  2550. {$endif TEST_PARTIAL_SYNTAX}
  2551. PrevLine:=Line;
  2552. until false;
  2553. DoUpdateAttrs:=CurLineNr;
  2554. {$ifdef TEST_PARTIAL_SYNTAX}
  2555. If LastSyntaxedLine<CurLineNr-1 then
  2556. LastSyntaxedLine:=CurLineNr-1;
  2557. if CurLineNr=GetLineCount then
  2558. begin
  2559. SyntaxComplete:=true;
  2560. DoSyntaxStateChanged;
  2561. end;
  2562. {$endif TEST_PARTIAL_SYNTAX}
  2563. end;
  2564. function TCustomCodeEditorCore.DoUpdateAttrsRange(Editor: PCustomCodeEditor; FromLine, ToLine: sw_integer;
  2565. Attrs: byte): sw_integer;
  2566. var Line: Sw_integer;
  2567. begin
  2568. Lock(Editor);
  2569. Line:=FromLine;
  2570. repeat
  2571. Line:=DoUpdateAttrs(Editor,Line,Attrs);
  2572. until (Line>=GetLineCount) or (Line>ToLine);
  2573. DoUpdateAttrsRange:=Line;
  2574. Unlock(Editor);
  2575. end;
  2576. procedure TCustomCodeEditorCore.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: sw_astring;AFlags : longint);
  2577. begin
  2578. Abstract;
  2579. end;
  2580. procedure TCustomCodeEditorCore.AddGroupedAction(AAction : byte);
  2581. begin
  2582. Abstract;
  2583. end;
  2584. procedure TCustomCodeEditorCore.CloseGroupedAction(AAction : byte);
  2585. begin
  2586. Abstract;
  2587. end;
  2588. function TCustomCodeEditorCore.GetUndoActionCount: sw_integer;
  2589. begin
  2590. Abstract;
  2591. GetUndoActionCount:=0;
  2592. end;
  2593. function TCustomCodeEditorCore.GetRedoActionCount: sw_integer;
  2594. begin
  2595. Abstract;
  2596. GetRedoActionCount:=0;
  2597. end;
  2598. destructor TCustomCodeEditorCore.Done;
  2599. begin
  2600. {$ifdef DEBUG}
  2601. if Bindings^.Count>0 then
  2602. ErrorBox('Internal error: there are still '+IntToStr(Bindings^.Count)+' editors '+
  2603. 'registered at TCodeEditorCode.Done!!!',nil);
  2604. {$endif}
  2605. if Assigned(Bindings) then Dispose(Bindings, Done); Bindings:=nil;
  2606. inherited Done;
  2607. end;
  2608. procedure TCustomCodeEditor.Lock;
  2609. begin
  2610. Inc(ELockFlag);
  2611. LockScreenUpdate;
  2612. end;
  2613. procedure TCustomCodeEditor.UnLock;
  2614. begin
  2615. {$ifdef DEBUG}
  2616. if Elockflag=0 then
  2617. Bug('negative lockflag',nil)
  2618. else
  2619. {$endif DEBUG}
  2620. UnlockScreenUpdate;
  2621. Dec(ELockFlag);
  2622. if (ELockFlag>0) then
  2623. Exit;
  2624. if DrawCalled then
  2625. DrawView;
  2626. If DrawCursorCalled then
  2627. Begin
  2628. DrawCursor;
  2629. DrawCursorCalled:=false;
  2630. End;
  2631. end;
  2632. procedure TCustomCodeEditor.DrawIndicator;
  2633. begin
  2634. { Abstract }
  2635. end;
  2636. procedure TCustomCodeEditor.AdjustSelectionPos(OldCurPosX, OldCurPosY: sw_integer; DeltaX, DeltaY: sw_integer);
  2637. var CP: TPoint;
  2638. begin
  2639. if ValidBlock=false then Exit;
  2640. CP.X:=OldCurPosX; CP.Y:=OldCurPosY;
  2641. if (PosToOfsP(SelStart)<=PosToOfsP(CP)) and (PosToOfsP(CP)<PosToOfsP(SelEnd)) then
  2642. begin
  2643. { OldCurPos is IN selection }
  2644. if (CP.Y=SelEnd.Y) then
  2645. begin
  2646. if ((SelStart.Y<>SelEnd.Y) or (SelStart.X<=CP.X)) and
  2647. (CP.X<=SelEnd.X) then
  2648. Inc(SelEnd.X,DeltaX);
  2649. end
  2650. else if (CP.Y=SelEnd.Y+DeltaY) then
  2651. Inc(SelEnd.X,DeltaX);
  2652. Inc(SelEnd.Y,DeltaY);
  2653. SelectionChanged;
  2654. end
  2655. else
  2656. if (PosToOfsP(CP)<=PosToOfsP(SelStart)) then
  2657. begin
  2658. { OldCurPos is BEFORE selection }
  2659. if (CP.Y=SelStart.Y) and (CP.Y=SelEnd.Y) and (DeltaY<0) then
  2660. begin
  2661. SelStart:=CurPos; SelEnd:=CurPos;
  2662. end
  2663. else
  2664. if (CP.Y=SelStart.Y) then
  2665. begin
  2666. if CP.X<SelStart.X then
  2667. Inc(SelStart.X,DeltaX);
  2668. end;
  2669. { else}
  2670. begin
  2671. Inc(SelStart.Y,DeltaY);
  2672. Inc(SelEnd.Y,DeltaY);
  2673. end;
  2674. if SelEnd.Y=CurPos.Y then Inc(SelEnd.X,DeltaX);
  2675. SelectionChanged;
  2676. end
  2677. else
  2678. begin
  2679. { OldCurPos is AFTER selection }
  2680. { actually we don't have to do anything here }
  2681. end;
  2682. end;
  2683. function TCustomCodeEditor.GetFlags: longint;
  2684. begin
  2685. { Abstract }
  2686. GetFlags:=0;
  2687. end;
  2688. procedure TCustomCodeEditor.SetFlags(AFlags: longint);
  2689. begin
  2690. { Abstract }
  2691. end;
  2692. function TCustomCodeEditor.GetModified: boolean;
  2693. begin
  2694. { Abstract }
  2695. GetModified:=true;
  2696. end;
  2697. procedure TCustomCodeEditor.SetModified(AModified: boolean);
  2698. begin
  2699. { Abstract }
  2700. end;
  2701. function TCustomCodeEditor.GetStoreUndo: boolean;
  2702. begin
  2703. { Abstract }
  2704. GetStoreUndo:=false;
  2705. end;
  2706. procedure TCustomCodeEditor.SetStoreUndo(AStore: boolean);
  2707. begin
  2708. { Abstract }
  2709. end;
  2710. function TCustomCodeEditor.GetSyntaxCompleted: boolean;
  2711. begin
  2712. { Abstract }
  2713. GetSyntaxCompleted:=true;
  2714. end;
  2715. procedure TCustomCodeEditor.SetSyntaxCompleted(SC : boolean);
  2716. begin
  2717. { Abstract }
  2718. end;
  2719. function TCustomCodeEditor.GetLastSyntaxedLine: sw_integer;
  2720. begin
  2721. Abstract;
  2722. GetLastSyntaxedLine:=0;
  2723. end;
  2724. procedure TCustomCodeEditor.SetLastSyntaxedLine(ALine: sw_integer);
  2725. begin
  2726. Abstract;
  2727. end;
  2728. function TCustomCodeEditor.IsNestedComments(X,Y : sw_integer): boolean;
  2729. begin
  2730. IsNestedComments:=false; {default behavior is no nested comments}
  2731. end;
  2732. function TCustomCodeEditor.NestedCommentsChangeCheck(CurLine : sw_integer):boolean;
  2733. begin
  2734. NestedCommentsChangeCheck:=false;
  2735. end;
  2736. function TCustomCodeEditor.IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
  2737. begin
  2738. IsFlagSet:=(GetFlags and AFlag)=AFlag;
  2739. end;
  2740. function TCustomCodeEditor.GetTabSize: integer;
  2741. begin
  2742. { Abstract }
  2743. GetTabSize:=5;
  2744. end;
  2745. procedure TCustomCodeEditor.SetTabSize(ATabSize: integer);
  2746. begin
  2747. { Abstract }
  2748. end;
  2749. function TCustomCodeEditor.GetIndentSize: integer;
  2750. begin
  2751. { Abstract }
  2752. GetIndentSize:=1;
  2753. end;
  2754. procedure TCustomCodeEditor.SetIndentSize(AIndentSize: integer);
  2755. begin
  2756. { Abstract }
  2757. end;
  2758. function TCustomCodeEditor.IsReadOnly: boolean;
  2759. begin
  2760. { Abstract }
  2761. IsReadOnly:=false;
  2762. end;
  2763. function TCustomCodeEditor.IsClipboard: Boolean;
  2764. begin
  2765. { Abstract }
  2766. IsClipboard:=false;
  2767. end;
  2768. function TCustomCodeEditor.GetLineCount: sw_integer;
  2769. begin
  2770. Abstract;
  2771. GetLineCount:=0;
  2772. end;
  2773. function TCustomCodeEditor.GetLine(LineNo: sw_integer): PCustomLine;
  2774. begin
  2775. Abstract;
  2776. GetLine:=nil;
  2777. end;
  2778. function TCustomCodeEditor.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
  2779. begin
  2780. Abstract;
  2781. CharIdxToLinePos:=0;
  2782. end;
  2783. function TCustomCodeEditor.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
  2784. begin
  2785. Abstract;
  2786. LinePosToCharIdx:=0;
  2787. end;
  2788. function TCustomCodeEditor.GetLineText(I: sw_integer): sw_astring;
  2789. begin
  2790. Abstract;
  2791. GetLineText:='';
  2792. end;
  2793. procedure TCustomCodeEditor.SetDisplayText(I: sw_integer;const S: sw_astring);
  2794. begin
  2795. Abstract;
  2796. end;
  2797. function TCustomCodeEditor.GetDisplayText(I: sw_integer): sw_astring;
  2798. begin
  2799. Abstract;
  2800. GetDisplayText:='';
  2801. end;
  2802. procedure TCustomCodeEditor.SetLineText(I: sw_integer;const S: sw_AString);
  2803. begin
  2804. Abstract;
  2805. end;
  2806. procedure TCustomCodeEditor.GetDisplayTextFormat(I: sw_integer;var DT,DF:sw_astring);
  2807. begin
  2808. Abstract;
  2809. end;
  2810. function TCustomCodeEditor.GetLineFormat(I: sw_integer): sw_astring;
  2811. begin
  2812. { Abstract }
  2813. GetLineFormat:='';
  2814. end;
  2815. procedure TCustomCodeEditor.SetLineFormat(I: sw_integer;const S: sw_astring);
  2816. begin
  2817. { Abstract }
  2818. end;
  2819. procedure TCustomCodeEditor.DeleteAllLines;
  2820. begin
  2821. Abstract;
  2822. end;
  2823. procedure TCustomCodeEditor.DeleteLine(I: sw_integer);
  2824. begin
  2825. Abstract;
  2826. end;
  2827. function TCustomCodeEditor.InsertLine(LineNo: sw_integer; const S: sw_astring): PCustomLine;
  2828. begin
  2829. Abstract;
  2830. InsertLine:=nil; { eliminate compiler warning }
  2831. end;
  2832. procedure TCustomCodeEditor.AddLine(const S: sw_astring);
  2833. begin
  2834. Abstract;
  2835. end;
  2836. function TCustomCodeEditor.GetErrorMessage: string;
  2837. begin
  2838. Abstract;
  2839. GetErrorMessage:='';
  2840. end;
  2841. procedure TCustomCodeEditor.SetErrorMessage(const S: string);
  2842. begin
  2843. Abstract;
  2844. end;
  2845. procedure TCustomCodeEditor.GetContent(ALines: PUnsortedStringCollection);
  2846. begin
  2847. Abstract;
  2848. end;
  2849. procedure TCustomCodeEditor.SetContent(ALines: PUnsortedStringCollection);
  2850. begin
  2851. Abstract;
  2852. end;
  2853. function TCustomCodeEditor.LoadFromStream(Stream: PFastBufStream): boolean;
  2854. begin
  2855. Abstract;
  2856. LoadFromStream:=false;
  2857. end;
  2858. function TCustomCodeEditor.SaveToStream(Stream: PStream): boolean;
  2859. var A,B: TPoint;
  2860. begin
  2861. A.Y:=0; A.X:=0;
  2862. B.Y:=GetLineCount-1;
  2863. if GetLineCount>0 then
  2864. B.X:=length(GetDisplayText(B.Y))
  2865. else
  2866. B.X:=0;
  2867. SaveToStream:=SaveAreaToStream(Stream,A,B);
  2868. end;
  2869. function TCustomCodeEditor.SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
  2870. begin
  2871. Abstract;
  2872. SaveAreaToStream:=false;
  2873. end;
  2874. function TCustomCodeEditor.LoadFromFile(const AFileName: string): boolean;
  2875. var S: PFastBufStream;
  2876. OK: boolean;
  2877. begin
  2878. New(S, Init(AFileName,stOpenRead,EditorTextBufSize));
  2879. OK:=Assigned(S);
  2880. {$ifdef TEST_PARTIAL_SYNTAX}
  2881. SetSyntaxCompleted(false);
  2882. { Idle necessary }
  2883. EventMask:=EventMask or evIdle;
  2884. {$endif TEST_PARTIAL_SYNTAX}
  2885. if OK then OK:=LoadFromStream(S);
  2886. if Assigned(S) then Dispose(S, Done);
  2887. LoadFromFile:=OK;
  2888. end;
  2889. function TCustomCodeEditor.SaveToFile(const AFileName: string): boolean;
  2890. var OK: boolean;
  2891. S: PBufStream;
  2892. begin
  2893. New(S, Init(AFileName,stCreate,EditorTextBufSize));
  2894. OK:=Assigned(S) and (S^.Status=stOK);
  2895. if OK then OK:=SaveToStream(S);
  2896. if Assigned(S) then Dispose(S, Done);
  2897. SaveToFile:=OK;
  2898. end;
  2899. procedure TCustomCodeEditor.AdjustBookMark(X, NewX, Y, NewY: sw_integer);
  2900. var P : PEditorBookMark;
  2901. Count,Index : sw_integer;
  2902. Line,NewLine : PCustomLine;
  2903. begin
  2904. if NewY=Y then
  2905. GetLine(Y)^.AdjustMark(@Self,X,NewX-X)
  2906. else
  2907. begin
  2908. Line:=GetLine(Y);
  2909. Count:=Line^.MarkCount(@Self);
  2910. if Count > 0 then
  2911. begin
  2912. NewLine:=GetLine(NewY);
  2913. for Index:=Count-1 downto 0 do
  2914. begin
  2915. P:=Line^.GetMark(@Self,Index);
  2916. if P^.Pos.X>=X then
  2917. begin
  2918. P^.Pos.X:=Max(0,P^.Pos.X+(NewX-X));
  2919. Line^.DeleteMark(@Self,P);
  2920. NewLine^.InsertMark(@Self,P);
  2921. end;
  2922. end;
  2923. end;
  2924. end;
  2925. end;
  2926. function TCustomCodeEditor.InsertFrom(Editor: PCustomCodeEditor): Boolean;
  2927. var OK: boolean;
  2928. CP,CI,RX,RSX,LineDelta,LineCount: Sw_integer;
  2929. StartPos,DestPos,BPos,EPos: TPoint;
  2930. LineStartX,LineEndX: Sw_integer;
  2931. TabSize,CharIdxStart,CharIdxEnd: Sw_integer;
  2932. S,DS,BeforeS,OrigS,AfterS: sw_astring;
  2933. VerticalBlock: boolean;
  2934. SEnd: TPoint;
  2935. begin
  2936. if Editor^.IsFlagSet(efVerticalBlocks) then
  2937. begin
  2938. NotImplemented;
  2939. Exit;
  2940. end;
  2941. Lock;
  2942. { every data in the clipboard gets a new line }
  2943. if (Clipboard=@Self) and (CurPos.X>0) then
  2944. InsertNewLine;
  2945. OK:=(Editor^.SelStart.X<>Editor^.SelEnd.X) or (Editor^.SelStart.Y<>Editor^.SelEnd.Y);
  2946. if OK then
  2947. begin
  2948. if not (Clipboard=@Self) and IsFlagSet(efOverwriteBlocks) and InSelectionArea then
  2949. DelSelect; {delete selection before paste}
  2950. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  2951. CurPos.X:=CharIdxToLinePos(CurPos.Y,CI); {tab space adjustment}
  2952. StartPos:=CurPos; DestPos:=CurPos;
  2953. EPos:=CurPos;
  2954. VerticalBlock:=Editor^.IsFlagSet(efVerticalBlocks);
  2955. LineDelta:=0; LineCount:=(Editor^.SelEnd.Y-Editor^.SelStart.Y)+1;
  2956. OK:=GetLineCount<MaxLineCount;
  2957. OrigS:=GetLineText(DestPos.Y);
  2958. BeforeS:=Copy(OrigS,1,LinePosToCharIdx(DestPos.Y,DestPos.X-1));
  2959. { we might need to add some spaces here,
  2960. but how many ? }
  2961. TabSize:=GetTabSize;
  2962. CP:=1; RX:=0;
  2963. while (CP<=length(BeforeS)) do
  2964. begin
  2965. if (BeforeS[CP]=TAB) then
  2966. Inc(RX,TabSize-(RX mod TabSize))
  2967. else
  2968. Inc(RX);
  2969. Inc(CP);
  2970. end;
  2971. BeforeS:=BeforeS+CharStr(' ',DestPos.X-RX);
  2972. AfterS:=Copy(OrigS,LinePosToCharIdx(DestPos.Y,DestPos.X),Length(OrigS));
  2973. BPos:=CurPos;
  2974. while OK and (LineDelta<LineCount) do
  2975. begin
  2976. S:=Editor^.GetLineText(Editor^.SelStart.Y+LineDelta);
  2977. if (LineDelta>0) and (VerticalBlock=false) then
  2978. begin
  2979. InsertLine(DestPos.Y,'');
  2980. EPOS.X:=0;EPos.Y:=DestPos.Y;
  2981. AddAction(eaInsertLine,BPos,EPos,'',GetFlags);
  2982. LimitsChanged;
  2983. end;
  2984. If LineDelta>0 then
  2985. BeforeS:='';
  2986. if (LineDelta=0) or VerticalBlock then
  2987. LineStartX:=Editor^.SelStart.X
  2988. else
  2989. LineStartX:=0;
  2990. if (LineDelta=LineCount-1) or VerticalBlock then
  2991. LineEndX:=Editor^.SelEnd.X-1
  2992. else
  2993. LineEndX:=Length(S);
  2994. CharIdxStart:=Editor^.LinePosToCharIdx(Editor^.SelStart.Y+LineDelta,LineStartX);
  2995. CharIdxEnd:=Editor^.LinePosToCharIdx(Editor^.SelStart.Y+LineDelta,LineEndX);
  2996. if LineEndX<LineStartX then
  2997. S:=''
  2998. else if VerticalBlock then
  2999. begin
  3000. S:=copy(S,CharIdxStart,CharIdxEnd-CharIdxStart+1);
  3001. S:=RExpand(S,Min(CharIdxEnd-CharIdxStart+1,Length(S)));
  3002. end else
  3003. S:=copy(S,CharIdxStart,CharIdxEnd-CharIdxStart+1);
  3004. if VerticalBlock=false then
  3005. begin
  3006. DS:=BeforeS+S;
  3007. CP:=1; RX:=0;
  3008. RSX :=0;
  3009. while (CP<=length(DS)) do
  3010. begin
  3011. if (DS[CP]=TAB) then
  3012. Inc(RX,TabSize-(RX mod TabSize))
  3013. else
  3014. Inc(RX);
  3015. if CP=length(BeforeS) then
  3016. RSX:=RX;
  3017. Inc(CP);
  3018. end;
  3019. if LineDelta=LineCount-1 then
  3020. begin
  3021. SetLineText(DestPos.Y,DS+AfterS);
  3022. BPos.X:=DestPos.X;BPos.Y:=DestPos.Y;
  3023. EPOS.X:=DestPos.X+RX-RSX;EPos.Y:=DestPos.Y;
  3024. AddAction(eaInsertText,BPos,EPos,S,GetFlags);
  3025. end
  3026. else
  3027. begin
  3028. SetLineText(DestPos.Y,DS);
  3029. BPos.X:=DestPos.X;BPos.Y:=DestPos.Y;
  3030. EPOS.X:=DestPos.X+RX-RSX;EPos.Y:=DestPos.Y;
  3031. AddAction(eaInsertText,BPos,EPos,S,GetFlags);
  3032. end;
  3033. BPos.X:=EPos.X;
  3034. if LineDelta=LineCount-1 then
  3035. begin
  3036. SEnd.Y:=DestPos.Y;
  3037. SEnd.X:=DestPos.X+RX-RSX;
  3038. end
  3039. else
  3040. begin
  3041. Inc(DestPos.Y);
  3042. DestPos.X:=0;
  3043. end;
  3044. end
  3045. else { if VerticalBlock=false then .. else }
  3046. begin
  3047. { this is not yet implemented !! PM }
  3048. S:=RExpand(S,LineEndX-LineStartX+1);
  3049. end;
  3050. Inc(LineDelta);
  3051. OK:=GetLineCount<MaxLineCount;
  3052. end;
  3053. if not OK then EditorDialog(edTooManyLines,nil);
  3054. { mainly to force eaMove insertion }
  3055. if not IsClipboard then
  3056. SetCurPtr(EPos.X,EPos.Y);
  3057. SetCurPtr(StartPos.X,StartPos.Y);
  3058. UpdateAttrs(StartPos.Y,attrAll);
  3059. SetModified(true);
  3060. LimitsChanged;
  3061. SetSelection(CurPos,SEnd);
  3062. if IsClipboard then
  3063. begin
  3064. Inc(DestPos.X,length(S));
  3065. SetCurPtr(DestPos.X,DestPos.Y);
  3066. end;
  3067. DrawView;
  3068. end;
  3069. UnLock;
  3070. InsertFrom:=OK;
  3071. end;
  3072. function TCustomCodeEditor.InsertText(const S: sw_astring): Boolean;
  3073. var I,CI: sw_integer;
  3074. OldPos: TPoint;
  3075. HoldUndo : boolean;
  3076. WasAutoBrackets : boolean;
  3077. begin
  3078. Lock;
  3079. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  3080. CurPos.X:=CharIdxToLinePos(CurPos.Y,CI); {tab space adjustment}
  3081. OldPos:=CurPos;
  3082. HoldUndo:=GetStoreUndo;
  3083. WasAutoBrackets:=GetAutoBrackets;
  3084. SetAutoBrackets(false);
  3085. SetStoreUndo(false);
  3086. for I:=1 to length(S) do
  3087. AddChar(S[I]);
  3088. InsertText:=true;
  3089. SetAutoBrackets(WasAutoBrackets);
  3090. SetStoreUndo(HoldUndo);
  3091. AddAction(eaInsertText,OldPos,CurPos,S,GetFlags);
  3092. UnLock;
  3093. end;
  3094. procedure TCustomCodeEditor.ModifiedChanged;
  3095. begin
  3096. { Abstract }
  3097. end;
  3098. procedure TCustomCodeEditor.PositionChanged;
  3099. begin
  3100. { Abstract }
  3101. end;
  3102. procedure TCustomCodeEditor.TabSizeChanged;
  3103. begin
  3104. { Abstract }
  3105. end;
  3106. procedure TCustomCodeEditor.SyntaxStateChanged;
  3107. begin
  3108. { Abstract }
  3109. end;
  3110. procedure TCustomCodeEditor.StoreUndoChanged;
  3111. begin
  3112. { Abstract }
  3113. end;
  3114. function TCustomCodeEditor.GetSpecSymbolCount(SpecClass: TSpecSymbolClass): integer;
  3115. begin
  3116. { Abstract }
  3117. GetSpecSymbolCount:=0;
  3118. end;
  3119. function TCustomCodeEditor.GetSpecSymbol(SpecClass: TSpecSymbolClass; Index: integer): pstring;
  3120. begin
  3121. Abstract;
  3122. GetSpecSymbol:=nil;
  3123. end;
  3124. function TCustomCodeEditor.IsReservedWord(const S: string): boolean;
  3125. begin
  3126. { Abstract }
  3127. IsReservedWord:=false;
  3128. end;
  3129. function TCustomCodeEditor.IsAsmReservedWord(const S: string): boolean;
  3130. begin
  3131. { Abstract }
  3132. IsAsmReservedWord:=false;
  3133. end;
  3134. function TCustomCodeEditor.TranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean;
  3135. begin
  3136. { Abstract }
  3137. TranslateCodeTemplate:=false;
  3138. end;
  3139. function TCustomCodeEditor.CompleteCodeWord(const WordS: string; var Text: string): boolean;
  3140. begin
  3141. { Abstract }
  3142. Text:='';
  3143. CompleteCodeWord:=false;
  3144. end;
  3145. function TCustomCodeEditor.GetCodeCompleteWord: string;
  3146. begin
  3147. { Abstract }
  3148. GetCodeCompleteWord:='';
  3149. end;
  3150. function TCustomCodeEditor.CreateFold(StartY,EndY: sw_integer; Collapsed: boolean): boolean;
  3151. var F,ParentF: PFold;
  3152. L: PCustomLine;
  3153. EI: PEditorLineInfo;
  3154. Y: sw_integer;
  3155. OK: boolean;
  3156. begin
  3157. OK:=true;
  3158. Lock;
  3159. for Y:=StartY to EndY do
  3160. begin
  3161. L:=GetLine(Y);
  3162. if assigned(L) then
  3163. EI:=L^.GetEditorInfo(@Self)
  3164. else
  3165. begin
  3166. CreateFold:=False;
  3167. exit;
  3168. end;
  3169. if Y=StartY then
  3170. ParentF:=EI^.Fold
  3171. else
  3172. OK:=OK and (EI^.Fold=ParentF);
  3173. if not OK then
  3174. Break;
  3175. end;
  3176. if OK then
  3177. begin
  3178. New(F, Init(@Self,ParentF,Collapsed));
  3179. for Y:=StartY to EndY do
  3180. GetLine(Y)^.GetEditorInfo(@Self)^.SetFold(F);
  3181. DrawView;
  3182. end;
  3183. UnLock;
  3184. CreateFold:=OK;
  3185. end;
  3186. procedure TCustomCodeEditor.FoldChanged(Fold: PFold);
  3187. var F: PFold;
  3188. I: sw_integer;
  3189. begin
  3190. for I:=0 to GetFoldCount-1 do
  3191. begin
  3192. F:=GetFold(I);
  3193. if F^.ParentFold=Fold then
  3194. FoldChanged(F);
  3195. end;
  3196. if Fold^.IsCollapsed then
  3197. begin
  3198. F:=GetLineFold(CurPos.Y); I:=CurPos.Y;
  3199. if F=Fold then
  3200. begin
  3201. while GetLineFold(I-1)=Fold do
  3202. Dec(I);
  3203. if I<>CurPos.Y then
  3204. SetCurPtr(CurPos.X,I);
  3205. end;
  3206. end;
  3207. DrawView;
  3208. end;
  3209. procedure TCustomCodeEditor.RemoveAllFolds;
  3210. var I: sw_integer;
  3211. L: PCustomLine;
  3212. begin
  3213. for I:=0 to GetLineCount-1 do
  3214. begin
  3215. L:=GetLine(I);
  3216. if not assigned(L) then exit;
  3217. with L^ do
  3218. with GetEditorInfo(@Self)^ do
  3219. SetFold(nil);
  3220. end;
  3221. DrawView;
  3222. end;
  3223. { to be called if CurPos has already been changed }
  3224. procedure TCustomCodeEditor.AdjustSelection(DeltaX, DeltaY: sw_integer);
  3225. begin
  3226. AdjustSelectionPos(CurPos.X-DeltaX,CurPos.Y-DeltaY,DeltaX,DeltaY);
  3227. end;
  3228. { to be called if CurPos has not yet been changed }
  3229. procedure TCustomCodeEditor.AdjustSelectionBefore(DeltaX, DeltaY: sw_integer);
  3230. begin
  3231. AdjustSelectionPos(CurPos.X,CurPos.Y,DeltaX,DeltaY);
  3232. end;
  3233. procedure TCustomCodeEditor.TrackCursor(centre:Tcentre);
  3234. var D,CP: TPoint;
  3235. begin
  3236. D:=Delta;
  3237. EditorToViewPoint(D,D); EditorToViewPoint(CurPos,CP);
  3238. if CP.Y<Delta.Y then D.Y:=CP.Y else
  3239. if CP.Y>Delta.Y+Size.Y-1 then D.Y:=CP.Y-Size.Y+1;
  3240. if CP.X<Delta.X then D.X:=CP.X else
  3241. if CP.X>Delta.X+Size.X-1 then D.X:=CP.X-Size.X+1;
  3242. if {((Delta.X<>D.X) or (Delta.Y<>D.Y)) and }centre=do_centre then
  3243. begin
  3244. { loose centering for debugger PM }
  3245. while (CP.Y-D.Y)<(Size.Y div 3) do Dec(D.Y);
  3246. while (CP.Y-D.Y)>2*(Size.Y div 3) do Inc(D.Y);
  3247. end;
  3248. ViewToEditorPoint(D,D);
  3249. if (Delta.X<>D.X) or (Delta.Y<>D.Y) then
  3250. ScrollTo(D.X,D.Y);
  3251. DrawCursor;
  3252. end;
  3253. procedure TCustomCodeEditor.ScrollTo(X, Y: sw_Integer);
  3254. begin
  3255. inherited ScrollTo(X,Y);
  3256. if (HScrollBar=nil) or (VScrollBar=nil) then
  3257. begin Delta.X:=X; Delta.Y:=Y; end;
  3258. DrawView;
  3259. end;
  3260. function TCustomCodeEditor.IsModal: boolean;
  3261. var IsM: boolean;
  3262. begin
  3263. IsM:=GetState(sfModal);
  3264. if Assigned(Owner) then
  3265. IsM:=IsM or Owner^.GetState(sfModal);
  3266. IsModal:=IsM;
  3267. end;
  3268. procedure TCustomCodeEditor.FlagsChanged(OldFlags: longint);
  3269. var I: sw_integer;
  3270. begin
  3271. Lock;
  3272. if ((OldFlags xor GetFlags) and efCodeComplete)<>0 then
  3273. ClearCodeCompleteWord;
  3274. SetInsertMode(IsFlagSet(efInsertMode));
  3275. if ((OldFlags xor GetFlags) and efFolds)<>0 then
  3276. if not IsFlagSet(efFolds) then
  3277. RemoveAllFolds;
  3278. if IsFlagSet(efSyntaxHighlight) then
  3279. UpdateAttrs(0,attrAll) else
  3280. for I:=0 to GetLineCount-1 do
  3281. SetLineFormat(I,'');
  3282. DrawView;
  3283. UnLock;
  3284. end;
  3285. procedure TCustomCodeEditor.LimitsChanged;
  3286. begin
  3287. Abstract;
  3288. end;
  3289. procedure TCustomCodeEditor.DoLimitsChanged;
  3290. begin
  3291. SetLimit(MaxLineLength+1,EditorToViewLine(GetLineCount));
  3292. end;
  3293. procedure TCustomCodeEditor.BindingsChanged;
  3294. begin
  3295. { Abstract }
  3296. end;
  3297. procedure TCustomCodeEditor.ContentsChanged;
  3298. begin
  3299. DrawView;
  3300. end;
  3301. procedure TCustomCodeEditor.ConvertEvent(var Event: TEvent);
  3302. var
  3303. Key: Word;
  3304. begin
  3305. if Event.What = evKeyDown then
  3306. begin
  3307. if (Event.KeyShift and kbShift <> 0) and
  3308. (Event.ScanCode >= $47) and (Event.ScanCode <= $51) then
  3309. Event.CharCode := #0;
  3310. Key := Event.KeyCode;
  3311. if KeyState <> 0 then
  3312. begin
  3313. if (Lo(Key) >= $01) and (Lo(Key) <= $1A) then Inc(Key, $40);
  3314. if (Lo(Key) >= $61) and (Lo(Key) <= $7A) then Dec(Key, $20);
  3315. end;
  3316. Key := ScanKeyMap(KeyMap[KeyState], Key);
  3317. if (KeyState<>0) and (Key=0) then
  3318. ClearEvent(Event); { eat second key if unrecognized after ^Q or ^K }
  3319. KeyState := 0;
  3320. if Key <> 0 then
  3321. if Hi(Key) = $FF then
  3322. begin
  3323. KeyState := Lo(Key);
  3324. ClearEvent(Event);
  3325. end
  3326. else
  3327. begin
  3328. Event.What := evCommand;
  3329. Event.Command := Key;
  3330. end;
  3331. end;
  3332. end;
  3333. procedure TCustomCodeEditor.SetLineFlagState(LineNo: sw_integer; Flags: longint; ASet: boolean);
  3334. var L: PCustomLine;
  3335. begin
  3336. { Avoid crashes if file was shorten for instance }
  3337. if LineNo>=GetLineCount then
  3338. exit;
  3339. L:=GetLine(LineNo);
  3340. if Assigned(L) then
  3341. with L^ do
  3342. if ASet then
  3343. SetFlags(GetFlags or Flags)
  3344. else
  3345. SetFlags(GetFlags and not Flags);
  3346. end;
  3347. procedure TCustomCodeEditor.SetLineFlagExclusive(Flags: longint; LineNo: sw_integer);
  3348. var I,Count: sw_integer;
  3349. L: PCustomLine;
  3350. begin
  3351. Lock;
  3352. Count:=GetLineCount;
  3353. for I:=0 to Count-1 do
  3354. begin
  3355. L:=GetLine(I);
  3356. if not assigned(L) then break;
  3357. if I=LineNo then
  3358. L^.SetFlags(L^.GetFlags or Flags)
  3359. else
  3360. L^.SetFlags(L^.GetFlags and (not Flags));
  3361. end;
  3362. UnLock;
  3363. end;
  3364. procedure TCustomCodeEditor.HandleEvent(var Event: TEvent);
  3365. var DontClear : boolean;
  3366. procedure CheckScrollBar(P: PScrollBar; var D: Sw_Integer);
  3367. begin
  3368. if (Event.InfoPtr = P) and (P^.Value <> D) then
  3369. begin
  3370. D := P^.Value;
  3371. DrawView;
  3372. end;
  3373. end;
  3374. procedure GetMousePos(var P: TPoint);
  3375. begin
  3376. MakeLocal(Event.Where,P);
  3377. Inc(P.X,Delta.X); Inc(P.Y,Delta.Y);
  3378. Dec(P.X,GetReservedColCount);
  3379. if P.X<0 then P.X:=0;
  3380. if P.Y<0 then P.Y:=0;
  3381. end;
  3382. type TCCAction = (ccCheck,ccClear,ccDontCare);
  3383. var
  3384. StartP,P: TPoint;
  3385. E: TEvent;
  3386. OldEvent : PEvent;
  3387. CCAction: TCCAction;
  3388. begin
  3389. CCAction:=ccClear;
  3390. E:=Event;
  3391. OldEvent:=CurEvent;
  3392. if (E.What and (evMouse or evKeyboard))<>0 then
  3393. CurEvent:=@E;
  3394. if (InASCIIMode=false) or (Event.What<>evKeyDown) then
  3395. if (Event.What<>evKeyDown) or (Event.KeyCode<>kbEnter) or (IsReadOnly=false) then
  3396. if (Event.What<>evKeyDown) or
  3397. ((Event.KeyCode<>kbEnter) and (Event.KeyCode<>kbEsc)) or
  3398. (GetCompleteState<>csOffering) then
  3399. ConvertEvent(Event);
  3400. case Event.What of
  3401. evMouseDown :
  3402. if (Event.Buttons=mbRightButton) then
  3403. begin
  3404. MakeLocal(Event.Where,P); Inc(P.X); Inc(P.Y);
  3405. LocalMenu(P);
  3406. ClearEvent(Event);
  3407. end else
  3408. if Event.Buttons=mbLeftButton then
  3409. begin
  3410. GetMousePos(P);
  3411. StartP:=P;
  3412. SetCurPtr(P.X,P.Y);
  3413. repeat
  3414. GetMousePos(P);
  3415. SetCurPtr(P.X,P.Y);
  3416. if PointOfs(P)<PointOfs(StartP)
  3417. then SetSelection(P,StartP)
  3418. else SetSelection(StartP,P);
  3419. DrawView;
  3420. until not MouseEvent(Event, evMouseMove+evMouseAuto);
  3421. DrawView;
  3422. end;
  3423. evKeyDown :
  3424. begin
  3425. { Scancode is almost never zero PM }
  3426. { this is supposed to enable entering of ASCII chars below 32,
  3427. which are normally interpreted as control chars. So, when you enter
  3428. Alt+24 (on the numeric pad) then this will normally move the cursor
  3429. one line down, but if you do it in ASCII mode (also after Ctrl+B)
  3430. then this will insert the ASCII #24 AnsiChar (upper arrow) in the
  3431. source code. - Gabor }
  3432. if InASCIIMode {and (Event.CharCode<>0)} then
  3433. begin
  3434. AddChar(Event.CharCode);
  3435. if (GetCompleteState<>csDenied) or (Event.CharCode=#32) then
  3436. CCAction:=ccCheck
  3437. else
  3438. CCAction:=ccClear;
  3439. end
  3440. else
  3441. begin
  3442. DontClear:=false;
  3443. case Event.KeyCode of
  3444. kbAltF10 :
  3445. Message(@Self,evCommand,cmLocalMenu,@Self);
  3446. kbEnter :
  3447. if IsReadOnly then
  3448. DontClear:=true else
  3449. if GetCompleteState=csOffering then
  3450. CodeCompleteApply
  3451. else
  3452. Message(@Self,evCommand,cmNewLine,nil);
  3453. kbEsc :
  3454. if GetCompleteState=csOffering then
  3455. CodeCompleteCancel else
  3456. if IsModal then
  3457. DontClear:=true;
  3458. else
  3459. case Event.CharCode of
  3460. #9,#32..#255 :
  3461. if (Event.CharCode=#9) and IsModal then
  3462. DontClear:=true
  3463. else
  3464. begin
  3465. NoSelect:=true;
  3466. AddChar(Event.CharCode);
  3467. NoSelect:=false;
  3468. if (GetCompleteState<>csDenied) or (Event.CharCode=#32) then
  3469. CCAction:=ccCheck
  3470. else
  3471. CCAction:=ccClear;
  3472. end;
  3473. else
  3474. DontClear:=true;
  3475. end; { case Event.CharCode .. }
  3476. end; { case Event.KeyCode .. }
  3477. if not DontClear then
  3478. ClearEvent(Event);
  3479. end;
  3480. InASCIIMode:=false;
  3481. end;
  3482. evCommand :
  3483. begin
  3484. DontClear:=false;
  3485. case Event.Command of
  3486. cmASCIIChar : InASCIIMode:=not InASCIIMode;
  3487. cmAddChar : AddChar(chr(longint(Event.InfoPtr)));
  3488. cmCharLeft : CharLeft;
  3489. cmCharRight : CharRight;
  3490. cmWordLeft : WordLeft;
  3491. cmWordRight : WordRight;
  3492. cmLineStart : LineStart;
  3493. cmLineEnd : LineEnd;
  3494. cmLineUp : LineUp;
  3495. cmLineDown : LineDown;
  3496. cmPageUp : PageUp;
  3497. cmPageDown : PageDown;
  3498. cmScrollOneUp : ScrollOneUp;
  3499. cmScrollOneDown:ScrollOneDown;
  3500. cmTextStart : TextStart;
  3501. cmTextEnd : TextEnd;
  3502. cmWindowStart : WindowStart;
  3503. cmWindowEnd : WindowEnd;
  3504. cmNewLine : begin
  3505. InsertNewLine;
  3506. TrackCursor(do_not_centre);
  3507. end;
  3508. cmBreakLine : BreakLine;
  3509. cmBackSpace : BackSpace;
  3510. cmDelChar : DelChar;
  3511. cmDelWord : DelWord;
  3512. cmDelToEndOfWord : DelToEndOfWord;
  3513. cmDelStart : DelStart;
  3514. cmDelEnd : DelEnd;
  3515. cmDelLine : DelLine;
  3516. cmInsMode : InsMode;
  3517. cmStartSelect : StartSelect;
  3518. cmHideSelect : HideSelect;
  3519. cmUpdateTitle : ;
  3520. cmEndSelect : EndSelect;
  3521. cmDelSelect : DelSelect;
  3522. cmCopyBlock : CopyBlock;
  3523. cmMoveBlock : MoveBlock;
  3524. cmIndentBlock : IndentBlock;
  3525. cmUnindentBlock : UnindentBlock;
  3526. cmSelStart : JumpSelStart;
  3527. cmSelEnd : JumpSelEnd;
  3528. cmLastCursorPos : JumpToLastCursorPos;
  3529. cmFindMatchingDelimiter : FindMatchingDelimiter(true);
  3530. cmFindMatchingDelimiterBack : FindMatchingDelimiter(false);
  3531. cmUpperCase : UpperCase;
  3532. cmLowerCase : LowerCase;
  3533. cmWordLowerCase : WordLowerCase;
  3534. cmWordUpperCase : WordUpperCase;
  3535. cmInsertOptions : InsertOptions;
  3536. cmToggleCase : ToggleCase;
  3537. cmCreateFold : CreateFoldFromBlock;
  3538. cmToggleFold : ToggleFold;
  3539. cmExpandFold : ExpandFold;
  3540. cmCollapseFold : CollapseFold;
  3541. cmJumpMark0..cmJumpMark9 : JumpMark(Event.Command-cmJumpMark0);
  3542. cmSetMark0..cmSetMark9 : DefineMark(Event.Command-cmSetMark0);
  3543. cmSelectWord : SelectWord;
  3544. cmSelectLine : SelectLine;
  3545. cmWriteBlock : WriteBlock;
  3546. cmReadBlock : ReadBlock;
  3547. cmPrintBlock : PrintBlock;
  3548. { ------ }
  3549. cmFind : Find;
  3550. cmReplace : Replace;
  3551. cmSearchAgain : DoSearchReplace;
  3552. cmJumpLine : GotoLine;
  3553. { ------ }
  3554. cmCut : ClipCut;
  3555. cmCopy : ClipCopy;
  3556. cmPaste : ClipPaste;
  3557. cmPasteText : PasteText(Event.InfoPtr,Event.Id);
  3558. cmSelectAll : SelectAll(true);
  3559. cmUnselect : SelectAll(false);
  3560. {$ifdef WinClipSupported}
  3561. cmCopyWin : ClipCopyWin;
  3562. cmPasteWin : ClipPasteWin;
  3563. {$endif WinClipSupported}
  3564. cmUndo : Undo;
  3565. cmRedo : Redo;
  3566. cmClear : DelSelect;
  3567. cmExpandCodeTemplate: ExpandCodeTemplate;
  3568. cmLocalMenu :
  3569. begin
  3570. P:=CurPos; Inc(P.X); Inc(P.Y);
  3571. LocalMenu(P);
  3572. end;
  3573. cmActivateMenu :
  3574. Message(Application,evCommand,cmMenu,nil);
  3575. else
  3576. begin
  3577. DontClear:=true;
  3578. CCAction:=ccDontCare;
  3579. end;
  3580. end;
  3581. if DontClear=false then
  3582. ClearEvent(Event);
  3583. end;
  3584. {$ifdef TEST_PARTIAL_SYNTAX}
  3585. evIdle :
  3586. begin
  3587. CCAction:=ccDontCare;
  3588. { Complete syntax by 20 lines increment }
  3589. { could already be quite lengthy on slow systems }
  3590. if not GetSyntaxCompleted then
  3591. UpdateAttrsRange(GetLastSyntaxedLine,GetLastSyntaxedLine+20,AttrAll);
  3592. end;
  3593. {$endif TEST_PARTIAL_SYNTAX}
  3594. evBroadcast :
  3595. begin
  3596. CCAction:=ccDontCare;
  3597. case Event.Command of
  3598. cmUpdate :
  3599. Update;
  3600. cmClearLineHighlights :
  3601. SetLineFlagExclusive(lfHighlightRow,-1);
  3602. cmResetDebuggerRow :
  3603. SetLineFlagExclusive(lfDebuggerRow,-1);
  3604. cmScrollBarChanged:
  3605. if (Event.InfoPtr = HScrollBar) or
  3606. (Event.InfoPtr = VScrollBar) then
  3607. begin
  3608. CheckScrollBar(HScrollBar, Delta.X);
  3609. CheckScrollBar(VScrollBar, Delta.Y);
  3610. end;
  3611. end;
  3612. end;
  3613. else CCAction:=ccDontCare;
  3614. end;
  3615. inherited HandleEvent(Event);
  3616. CurEvent:=OldEvent;
  3617. case CCAction of
  3618. ccCheck : CodeCompleteCheck;
  3619. ccClear : ClearCodeCompleteWord;
  3620. end;
  3621. end;
  3622. procedure TCustomCodeEditor.UpdateUndoRedo(cm : word; action : byte);
  3623. var UndoMenu : PMenuItem;
  3624. begin
  3625. UndoMenu:=PAdvancedMenuBar(MenuBar)^.GetMenuItem(cm);
  3626. if assigned(UndoMenu) then
  3627. begin
  3628. If assigned(UndoMenu^.Param) then
  3629. DisposeStr(UndoMenu^.Param);
  3630. if action<lastaction then
  3631. UndoMenu^.Param:=NewStr(ActionString[action]);
  3632. end;
  3633. end;
  3634. procedure TCustomCodeEditor.Update;
  3635. begin
  3636. Lock;
  3637. LimitsChanged;
  3638. SelectionChanged;
  3639. HighlightChanged;
  3640. UnLock;
  3641. end;
  3642. function TCustomCodeEditor.GetLocalMenu: PMenu;
  3643. begin
  3644. GetLocalMenu:=nil;
  3645. end;
  3646. function TCustomCodeEditor.GetCommandTarget: PView;
  3647. begin
  3648. GetCommandTarget:=@Self;
  3649. end;
  3650. function TCustomCodeEditor.CreateLocalMenuView(var Bounds: TRect; M: PMenu): PMenuPopup;
  3651. var MV: PMenuPopup;
  3652. begin
  3653. New(MV, Init(Bounds, M));
  3654. CreateLocalMenuView:=MV;
  3655. end;
  3656. procedure TCustomCodeEditor.LocalMenu(P: TPoint);
  3657. var M: PMenu;
  3658. MV: PMenuPopUp;
  3659. R: TRect;
  3660. Re: word;
  3661. begin
  3662. M:=GetLocalMenu;
  3663. if M=nil then Exit;
  3664. if LastLocalCmd<>0 then
  3665. M^.Default:=SearchMenuItem(M,LastLocalCmd);
  3666. Desktop^.GetExtent(R);
  3667. MakeGlobal(P,R.A); {Desktop^.MakeLocal(R.A,R.A);}
  3668. MV:=CreateLocalMenuView(R,M);
  3669. Re:=Application^.ExecView(MV);
  3670. if M^.Default=nil then LastLocalCmd:=0
  3671. else LastLocalCmd:=M^.Default^.Command;
  3672. Dispose(MV, Done);
  3673. if Re<>0 then
  3674. Message(GetCommandTarget,evCommand,Re,@Self);
  3675. end;
  3676. function TCustomCodeEditor.GetReservedColCount: sw_integer;
  3677. var LSX: sw_integer;
  3678. begin
  3679. if IsFlagSet(efFolds) then LSX:=GetFoldStringWidth else LSX:=0;
  3680. GetReservedColCount:=LSX;
  3681. end;
  3682. procedure TCustomCodeEditor.Draw;
  3683. function GetEIFold(EI: PEditorLineInfo): PFold;
  3684. begin
  3685. if Assigned(EI) then GetEIFold:=EI^.Fold else GetEIFold:=nil;
  3686. end;
  3687. var SelectColor,
  3688. HighlightColColor,
  3689. HighlightRowColor,
  3690. ErrorMessageColor : word;
  3691. B: TDrawBuffer;
  3692. X,Y,AX,AY,MaxX,LSX: sw_integer;
  3693. PX: TPoint;
  3694. LineCount: sw_integer;
  3695. Line: PCustomLine;
  3696. LineText,Format: sw_astring;
  3697. isBreak : boolean;
  3698. C: AnsiChar;
  3699. FreeFormat: array[0..MaxLineLength] of boolean;
  3700. Color: word;
  3701. ColorTab: array[coFirstColor..coLastColor] of word;
  3702. ErrorLine: integer;
  3703. ErrorMsg: string[MaxViewWidth];
  3704. function CombineColors(Orig,Modifier: byte): byte;
  3705. var Color: byte;
  3706. begin
  3707. if (Modifier and $0f)=0 then
  3708. Color:=(Orig and $0f) or (Modifier and $f0)
  3709. else
  3710. Color:=(Orig and $f0) or (Modifier and $0f);
  3711. { do not allow invisible }
  3712. { use white as foreground in this case }
  3713. if (Color and $f) = ((Color div $10) and $7) then
  3714. Color:=(Color and $F0) or $F;
  3715. CombineColors:=Color;
  3716. end;
  3717. var ShowIndent:boolean;
  3718. FoldPrefix,FoldSuffix: string;
  3719. { SkipLine: boolean;}
  3720. { FoldStartLine: sw_integer;}
  3721. begin
  3722. if ELockFlag>0 then
  3723. begin
  3724. DrawCalled:=true;
  3725. Exit;
  3726. end;
  3727. DrawCalled:=false;
  3728. ErrorMsg:=copy(GetErrorMessage,1,MaxViewWidth);
  3729. if ErrorMsg='' then ErrorLine:=-1 else
  3730. if (CurPos.Y-Delta.Y)<(Size.Y div 2) then ErrorLine:=Size.Y-1
  3731. else ErrorLine:=0;
  3732. LineCount:=GetLineCount;
  3733. ColorTab[coTextColor]:=GetColor(1);
  3734. ColorTab[coWhiteSpaceColor]:=GetColor(2);
  3735. ColorTab[coCommentColor]:=GetColor(3);
  3736. ColorTab[coReservedWordColor]:=GetColor(4);
  3737. ColorTab[coIdentifierColor]:=GetColor(5);
  3738. ColorTab[coStringColor]:=GetColor(6);
  3739. ColorTab[coNumberColor]:=GetColor(7);
  3740. ColorTab[coAssemblerColor]:=GetColor(8);
  3741. ColorTab[coSymbolColor]:=GetColor(9);
  3742. ColorTab[coDirectiveColor]:=GetColor(13);
  3743. ColorTab[coHexNumberColor]:=GetColor(14);
  3744. ColorTab[coTabColor]:=GetColor(15);
  3745. { break same as error }
  3746. ColorTab[coBreakColor]:=GetColor(16);
  3747. ColorTab[coAsmReservedColor]:=GetColor(17);
  3748. SelectColor:=GetColor(10);
  3749. HighlightColColor:=GetColor(11);
  3750. HighlightRowColor:=GetColor(12);
  3751. ErrorMessageColor:=GetColor(16);
  3752. ShowIndent:=IsFlagSet(efShowIndent) and IsFlagSet(efSyntaxHighlight);
  3753. {$ifdef TEST_PARTIAL_SYNTAX}
  3754. If (not GetSyntaxCompleted) and (GetLastSyntaxedLine<Delta.Y+Size.Y) then
  3755. UpdateAttrsRange(GetLastSyntaxedLine,Delta.Y+Size.Y,AttrAll);
  3756. {$endif TEST_PARTIAL_SYNTAX}
  3757. LSX:=GetReservedColCount;
  3758. Y:=0; AY:=Delta.Y;
  3759. for Y:=0 to Size.Y-1 do
  3760. begin
  3761. if Y=ErrorLine then
  3762. begin
  3763. MoveChar(B,' ',ErrorMessageColor,Size.X);
  3764. MoveStr(B,ErrorMsg,ErrorMessageColor);
  3765. WriteLine(0,Y,Size.X,1,B);
  3766. end
  3767. else
  3768. begin
  3769. AY:=ViewToEditorLine(Delta.Y+Y);
  3770. if (0<=AY) and (AY<LineCount) then
  3771. begin
  3772. Line:=GetLine(AY);
  3773. if assigned(Line) then
  3774. begin
  3775. IsBreak:=Line^.IsFlagSet(lfBreakpoint);
  3776. end
  3777. else
  3778. begin
  3779. IsBreak:=false;
  3780. end;
  3781. end
  3782. else
  3783. begin
  3784. Line:=nil;
  3785. IsBreak:=false;
  3786. end;
  3787. begin
  3788. Color:=ColorTab[coTextColor];
  3789. FillChar(FreeFormat,SizeOf(FreeFormat),1);
  3790. MoveChar(B,' ',Color,Size.X);
  3791. GetDisplayTextFormat(AY,LineText,Format);
  3792. if ShowIndent and (length(Format)=length(LineText)) then
  3793. for X:=1 to length(LineText) do
  3794. begin
  3795. if LineText[X] <> ' ' then break;
  3796. if (X>1 ) and (X and 1 = 1) then
  3797. if ord(Format[X]) in [coWhiteSpaceColor,coTabColor] then
  3798. LineText[X]:=#179; { | show line indent }
  3799. end;
  3800. MaxX:=Min(Delta.X+1+Size.X,MaxLineLength);
  3801. for X:=(MaxX-Size.X) to MaxX+1 do
  3802. begin
  3803. AX:=Delta.X+X-1;
  3804. if X<=length(LineText) then C:=LineText[X] else C:=' ';
  3805. PX.X:=AX-Delta.X; PX.Y:=AY;
  3806. if (Highlight.A.X<>Highlight.B.X) or (Highlight.A.Y<>Highlight.B.Y) then
  3807. { there's a highlight }
  3808. begin
  3809. if (PointOfs(Highlight.A)<=PointOfs(PX)) and (PointOfs(PX)<PointOfs(Highlight.B)) then
  3810. begin
  3811. Color:=SelectColor;
  3812. FreeFormat[X]:=false;
  3813. end;
  3814. end
  3815. else
  3816. { no highlight }
  3817. begin
  3818. if IsFlagSet(efVerticalBlocks) then
  3819. begin
  3820. if (SelStart.X<=AX) and (AX<=SelEnd.X) and
  3821. (SelStart.Y<=AY) and (AY<=SelEnd.Y) then
  3822. begin
  3823. Color:=SelectColor; FreeFormat[X]:=false;
  3824. end;
  3825. end
  3826. else
  3827. if PointOfs(SelStart)<>PointOfs(SelEnd) then
  3828. if (PointOfs(SelStart)<=PointOfs(PX)) and (PointOfs(PX)<PointOfs(SelEnd)) then
  3829. begin
  3830. Color:=SelectColor; FreeFormat[X]:=false;
  3831. end;
  3832. end; { no highlight }
  3833. if FreeFormat[X] then
  3834. if X<=length(Format) then
  3835. {Color:=ColorTab[ord(Format[X])] else Color:=ColorTab[coTextColor];
  3836. this give BoundsCheckError with -Cr quite often PM }
  3837. Color:=ColorTab[ord(Format[X]) mod (coLastColor + 1)] else Color:=ColorTab[coTextColor];
  3838. if IsFlagSet(efHighlightRow) and
  3839. (PX.Y=CurPos.Y) then
  3840. begin
  3841. Color:=CombineColors(Color,HighlightRowColor);
  3842. FreeFormat[X]:=false;
  3843. end;
  3844. if IsFlagSet(efHighlightColumn) and (PX.X=CurPos.X) then
  3845. begin
  3846. Color:=CombineColors(Color,HighlightColColor);
  3847. FreeFormat[X]:=false;
  3848. end;
  3849. if Assigned(Line) and Line^.IsFlagSet(lfHighlightRow) then
  3850. begin
  3851. Color:=CombineColors(Color,HighlightRowColor);
  3852. FreeFormat[X]:=false;
  3853. end;
  3854. if isbreak then
  3855. begin
  3856. Color:=ColorTab[coBreakColor];
  3857. FreeFormat[X]:=false;
  3858. end;
  3859. if Assigned(Line) and Line^.isFlagSet(lfDebuggerRow) then
  3860. begin
  3861. Color:=CombineColors(Color,HighlightRowColor);
  3862. FreeFormat[X]:=false;
  3863. end;
  3864. if (0<=LSX+X-1-Delta.X) and (LSX+X-1-Delta.X<MaxViewWidth) then
  3865. MoveChar(B[LSX+X-1-Delta.X],C,Color,1);
  3866. end; { for X:=1 to ... }
  3867. if IsFlagSet(efFolds) then
  3868. begin
  3869. GetFoldStrings(AY,FoldPrefix,FoldSuffix);
  3870. MoveStr(B[0],FoldPrefix,ColorTab[coTextColor]);
  3871. if FoldSuffix<>'' then
  3872. MoveStr(B[Size.X-1-length(FoldSuffix)],FoldSuffix,ColorTab[coTextColor]);
  3873. end;
  3874. WriteLine(0,Y,Size.X,1,B);
  3875. end; { if not SkipLine ... }
  3876. end; { not errorline }
  3877. end; { while (Y<Size.Y) ... }
  3878. DrawCursor;
  3879. end;
  3880. procedure TCustomCodeEditor.DrawCursor;
  3881. var InsertMode : boolean;
  3882. begin
  3883. if Elockflag>0 then
  3884. DrawCursorCalled:=true
  3885. else
  3886. begin
  3887. SetCursor(GetReservedColCount+CurPos.X-Delta.X,EditorToViewLine(CurPos.Y)-Delta.Y);
  3888. InsertMode:=Overwrite;
  3889. if IsFlagSet (efBlockInsCursor) then
  3890. InsertMode:=not InsertMode; {revers insert and overwrite mode cursor shapes}
  3891. SetState(sfCursorIns,InsertMode);
  3892. end;
  3893. end;
  3894. procedure TCustomCodeEditor.ResetCursor;
  3895. begin
  3896. if Elockflag>0 then
  3897. begin
  3898. DrawCursorCalled:=true;
  3899. exit;
  3900. end
  3901. else
  3902. inherited ResetCursor;
  3903. end;
  3904. function TCustomCodeEditor.Overwrite: boolean;
  3905. begin
  3906. Overwrite:=not IsFlagSet(efInsertMode);
  3907. end;
  3908. procedure TCustomCodeEditor.SetCodeCompleteWord(const S: string);
  3909. begin
  3910. if S<>'' then
  3911. SetCompleteState(csOffering)
  3912. else
  3913. SetCompleteState(csInactive);
  3914. end;
  3915. procedure TCustomCodeEditor.ClearCodeCompleteWord;
  3916. begin
  3917. SetCodeCompleteWord('');
  3918. SetCompleteState(csInactive);
  3919. end;
  3920. function TCustomCodeEditor.GetCompleteState: TCompleteState;
  3921. begin
  3922. { Abstract }
  3923. GetCompleteState:=csInactive;
  3924. end;
  3925. procedure TCustomCodeEditor.SetCompleteState(AState: TCompleteState);
  3926. begin
  3927. { Abstract }
  3928. end;
  3929. function TCustomCodeEditor.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
  3930. begin
  3931. Abstract;
  3932. UpdateAttrs:=-1;
  3933. end;
  3934. function TCustomCodeEditor.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
  3935. begin
  3936. Abstract;
  3937. UpdateAttrsRange:=-1;
  3938. end;
  3939. procedure TCustomCodeEditor.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: sw_astring;AFlags : longint);
  3940. begin
  3941. { Abstract }
  3942. end;
  3943. procedure TCustomCodeEditor.AddGroupedAction(AAction : byte);
  3944. begin
  3945. { Abstract }
  3946. end;
  3947. procedure TCustomCodeEditor.CloseGroupedAction(AAction : byte);
  3948. begin
  3949. { Abstract }
  3950. end;
  3951. function TCustomCodeEditor.GetUndoActionCount: sw_integer;
  3952. begin
  3953. { Abstract }
  3954. GetUndoActionCount:=0;
  3955. end;
  3956. function TCustomCodeEditor.GetRedoActionCount: sw_integer;
  3957. begin
  3958. { Abstract }
  3959. GetRedoActionCount:=0;
  3960. end;
  3961. function TCustomCodeEditor.GetMaxFoldLevel: sw_integer;
  3962. var Max,L,I: sw_integer;
  3963. begin
  3964. Max:=0;
  3965. for I:=0 to GetFoldCount-1 do
  3966. begin
  3967. L:=GetFold(I)^.GetLevel;
  3968. if L>Max then Max:=L;
  3969. end;
  3970. GetMaxFoldLevel:=Max;
  3971. end;
  3972. function TCustomCodeEditor.GetFoldStringWidth: sw_integer;
  3973. begin
  3974. GetFoldStringWidth:=GetMaxFoldLevel;
  3975. end;
  3976. procedure TCustomCodeEditor.GetFoldStrings(EditorLine: sw_integer; var Prefix, Suffix: openstring);
  3977. var F: PFold;
  3978. C: AnsiChar;
  3979. begin
  3980. Prefix:=CharStr(' ',GetFoldStringWidth); Suffix:='';
  3981. F:=GetLineFold(EditorLine);
  3982. if Assigned(F) then
  3983. begin
  3984. if F^.Collapsed_ then C:=#27 else C:=#26;
  3985. Prefix[1+F^.GetLevel]:=C;
  3986. if F^.Collapsed_ then
  3987. Suffix:='('+IntToStr(F^.GetLineCount)+')';
  3988. end;
  3989. end;
  3990. function TCustomCodeEditor.GetFoldCount: sw_integer;
  3991. begin
  3992. GetFoldCount:=0;
  3993. end;
  3994. function TCustomCodeEditor.GetFold(Index: sw_integer): PFold;
  3995. begin
  3996. GetFold:=nil;
  3997. end;
  3998. procedure TCustomCodeEditor.RegisterFold(AFold: PFold);
  3999. begin
  4000. Abstract;
  4001. end;
  4002. procedure TCustomCodeEditor.UnRegisterFold(AFold: PFold);
  4003. begin
  4004. Abstract;
  4005. end;
  4006. procedure TCustomCodeEditor.Indent;
  4007. var S, PreS: sw_astring;
  4008. Shift: integer;
  4009. begin
  4010. S:=GetLineText(CurPos.Y);
  4011. if CurPos.Y>0 then
  4012. PreS:=RTrim(GetLineText(CurPos.Y-1),not IsFlagSet(efUseTabCharacters))
  4013. else
  4014. PreS:='';
  4015. if CurPos.X>=length(PreS) then
  4016. Shift:=GetTabSize
  4017. else
  4018. begin
  4019. Shift:=1;
  4020. while (CurPos.X+Shift<length(PreS)) and (PreS[CurPos.X+Shift]<>' ') do
  4021. Inc(Shift);
  4022. end;
  4023. SetLineText(CurPos.Y,RExpand(copy(S,1,CurPos.X+1),CurPos.X+1)+CharStr(' ',Shift)+copy(S,CurPos.X+2,Length(S)));
  4024. SetCurPtr(CurPos.X+Shift,CurPos.Y);
  4025. UpdateAttrs(CurPos.Y,attrAll);
  4026. DrawLines(CurPos.Y);
  4027. SetModified(true);
  4028. end;
  4029. procedure TCustomCodeEditor.CharLeft;
  4030. begin
  4031. if CurPos.X=0 then Exit;
  4032. SetCurPtr(CurPos.X-1,CurPos.Y);
  4033. end;
  4034. procedure TCustomCodeEditor.CharRight;
  4035. begin
  4036. if CurPos.X>=MaxLineLength then
  4037. Exit;
  4038. SetCurPtr(CurPos.X+1,CurPos.Y);
  4039. end;
  4040. procedure TCustomCodeEditor.WordLeft;
  4041. var X, Y: sw_integer;
  4042. Line: sw_astring;
  4043. GotIt,FoundNonSeparator: boolean;
  4044. begin
  4045. X:=CurPos.X;
  4046. Y:=CurPos.Y;
  4047. GotIt:=false;
  4048. FoundNonSeparator:=false;
  4049. while (Y>=0) do
  4050. begin
  4051. if Y=CurPos.Y then
  4052. begin
  4053. X:=length(GetDisplayText(Y));
  4054. if CurPos.X<X then
  4055. X:=CurPos.X; Dec(X);
  4056. if (X=-1) then
  4057. begin
  4058. Dec(Y);
  4059. if Y>=0 then
  4060. X:=length(GetDisplayText(Y));
  4061. Break;
  4062. end;
  4063. end
  4064. else
  4065. X:=length(GetDisplayText(Y))-1;
  4066. Line:=GetDisplayText(Y);
  4067. while (X>=0) and (GotIt=false) do
  4068. begin
  4069. if FoundNonSeparator then
  4070. begin
  4071. if IsWordSeparator(Line[X+1]) then
  4072. begin
  4073. Inc(X);
  4074. GotIt:=true;
  4075. Break;
  4076. end;
  4077. end
  4078. else
  4079. if not IsWordSeparator(Line[X+1]) then
  4080. FoundNonSeparator:=true;
  4081. Dec(X);
  4082. if (X=0) and (IsWordSeparator(Line[1])=false) then
  4083. begin
  4084. GotIt:=true;
  4085. Break;
  4086. end;
  4087. end;
  4088. if GotIt then
  4089. Break;
  4090. X:=0;
  4091. Dec(Y);
  4092. if Y>=0 then
  4093. begin
  4094. X:=length(GetDisplayText(Y));
  4095. Break;
  4096. end;
  4097. end;
  4098. if Y<0 then Y:=0; if X<0 then X:=0;
  4099. SetCurPtr(X,Y);
  4100. end;
  4101. procedure TCustomCodeEditor.WordRight;
  4102. var X, Y: sw_integer;
  4103. Line: sw_astring;
  4104. GotIt: boolean;
  4105. begin
  4106. X:=CurPos.X; Y:=CurPos.Y; GotIt:=false;
  4107. while (Y<GetLineCount) do
  4108. begin
  4109. if Y=CurPos.Y then
  4110. begin
  4111. X:=CurPos.X; Inc(X);
  4112. if (X>length(GetDisplayText(Y))-1) then
  4113. begin Inc(Y); X:=0; end;
  4114. end else X:=0;
  4115. Line:=GetDisplayText(Y);
  4116. while (X<=length(Line)+1) and (GotIt=false) and (Line<>'') do
  4117. begin
  4118. if X=length(Line)+1 then begin GotIt:=true; Dec(X); Break end;
  4119. if IsWordSeparator(Line[X]) then
  4120. begin
  4121. while (Y<GetLineCount) and
  4122. (X<=length(Line)) and (IsWordSeparator(Line[X])) do
  4123. begin
  4124. Inc(X);
  4125. if X>=length(Line) then
  4126. begin GotIt:=true; Dec(X); Break; end;
  4127. end;
  4128. if (GotIt=false) and (X<length(Line)) then
  4129. begin
  4130. Dec(X);
  4131. GotIt:=true;
  4132. Break;
  4133. end;
  4134. end;
  4135. Inc(X);
  4136. end;
  4137. if GotIt then Break;
  4138. X:=0;
  4139. Inc(Y);
  4140. if (Y<GetLineCount) then
  4141. begin
  4142. Line:=GetDisplayText(Y);
  4143. if (Line<>'') and (IsWordSeparator(Line[1])=false) then Break;
  4144. end;
  4145. end;
  4146. if Y=GetLineCount then Y:=GetLineCount-1;
  4147. SetCurPtr(X,Y);
  4148. end;
  4149. procedure TCustomCodeEditor.LineStart;
  4150. begin
  4151. SetCurPtr(0,CurPos.Y);
  4152. end;
  4153. procedure TCustomCodeEditor.LineEnd;
  4154. var
  4155. s : sw_astring;
  4156. i : longint;
  4157. begin
  4158. if CurPos.Y<GetLineCount then
  4159. begin
  4160. s:=GetDisplayText(CurPos.Y);
  4161. i:=length(s);
  4162. while (i>0) and (s[i]=' ') do
  4163. dec(i);
  4164. i:=Min(i,MaxLineLength);
  4165. SetCurPtr(i,CurPos.Y);
  4166. end
  4167. else
  4168. SetCurPtr(0,CurPos.Y);
  4169. end;
  4170. function TCustomCodeEditor.NextVisibleLine(StartLine: sw_integer; Down: boolean): sw_integer;
  4171. var Count,NL: sw_integer;
  4172. begin
  4173. if Down then
  4174. begin
  4175. Count:=GetLineCount;
  4176. NL:=StartLine;
  4177. while (NL<Count-1) and not IsLineVisible(NL) do
  4178. Inc(NL);
  4179. if NL>=Count then
  4180. NL:=-1;
  4181. end
  4182. else
  4183. begin
  4184. NL:=StartLine;
  4185. while (NL>0) and not IsLineVisible(NL) do
  4186. Dec(NL);
  4187. end;
  4188. if not IsLineVisible(NL) then
  4189. NL:=-1;
  4190. NextVisibleLine:=NL;
  4191. end;
  4192. procedure TCustomCodeEditor.LineUp;
  4193. var NL: sw_integer;
  4194. begin
  4195. NL:=NextVisibleLine(CurPos.Y-1,false);
  4196. if NL<>-1 then
  4197. SetCurPtr(CurPos.X,NL);
  4198. end;
  4199. procedure TCustomCodeEditor.LineDown;
  4200. var NL: sw_integer;
  4201. begin
  4202. NL:=NextVisibleLine(CurPos.Y+1,true);
  4203. if NL<>-1 then
  4204. SetCurPtr(CurPos.X,NL);
  4205. end;
  4206. procedure TCustomCodeEditor.PageUp;
  4207. var NL: sw_integer;
  4208. begin
  4209. ScrollTo(Delta.X,Max(Delta.Y-Size.Y,0));
  4210. NL:=Max(CurPos.Y-(Size.Y),0);
  4211. if not IsLineVisible(NL) then
  4212. NL:=NextVisibleLine(NL,false);
  4213. if NL>=0 then
  4214. SetCurPtr(CurPos.X,Max(0,NL));
  4215. end;
  4216. procedure TCustomCodeEditor.PageDown;
  4217. var NL: sw_integer;
  4218. begin
  4219. ScrollTo(Delta.X,Min(Delta.Y+Size.Y,GetLineCount-1));
  4220. NL:=Min(CurPos.Y+(Size.Y{-1}),GetLineCount-1);
  4221. if not IsLineVisible(NL) then
  4222. NL:=NextVisibleLine(NL,true);
  4223. if NL>=0 then
  4224. SetCurPtr(CurPos.X,Min(GetLineCount-1,NL));
  4225. end;
  4226. procedure TCustomCodeEditor.ScrollOneUp;
  4227. var NL: sw_integer;
  4228. LinesScroll : sw_integer;
  4229. cursorInVisibleArea : boolean;
  4230. begin
  4231. LinesScroll:=-1;
  4232. cursorInVisibleArea:= (CurPos.Y>=Delta.Y) and (CurPos.Y<(Delta.Y+Size.Y)); {ignore folds here}
  4233. NL:=NextVisibleLine(CurPos.Y-1,false);
  4234. ScrollTo(Delta.X, Delta.Y + LinesScroll);
  4235. if cursorInVisibleArea and (CurPos.Y>=(Delta.Y+Size.Y)) then {do not allow corsor leave visible area}
  4236. if NL<>-1 then
  4237. SetCurPtr(CurPos.X,NL); {cursor stick to window bottom line}
  4238. end;
  4239. procedure TCustomCodeEditor.ScrollOneDown;
  4240. var NL: sw_integer;
  4241. LinesScroll : sw_integer;
  4242. cursorInVisibleArea : boolean;
  4243. begin
  4244. LinesScroll:=1;
  4245. cursorInVisibleArea:= (CurPos.Y>=Delta.Y) and (CurPos.Y<(Delta.Y+Size.Y)); {ignore folds here}
  4246. NL:=NextVisibleLine(CurPos.Y+1,true);
  4247. ScrollTo(Delta.X, Delta.Y + LinesScroll);
  4248. if cursorInVisibleArea and (CurPos.Y<Delta.Y) then {do not allow corsor leave visible area}
  4249. if NL>=0 then
  4250. SetCurPtr(CurPos.X,Min(GetLineCount-1,NL)); {cursor stick to window top line}
  4251. end;
  4252. procedure TCustomCodeEditor.TextStart;
  4253. begin
  4254. SetCurPtr(0,0);
  4255. end;
  4256. procedure TCustomCodeEditor.TextEnd;
  4257. var s : sw_astring;
  4258. i : longint;
  4259. begin
  4260. s:=GetDisplayText(GetLineCount-1);
  4261. i:=length(s);
  4262. while (i>0) and (s[i]=' ') do
  4263. dec(i);
  4264. i:=Min(i,MaxLineLength);
  4265. SetCurPtr(i,GetLineCount-1);
  4266. end;
  4267. procedure TCustomCodeEditor.WindowStart;
  4268. begin
  4269. if not NoSelect and ShouldExtend then
  4270. TextStart {select to start}
  4271. else
  4272. SetCurPtr(CurPos.X,Delta.Y);
  4273. end;
  4274. procedure TCustomCodeEditor.WindowEnd;
  4275. begin
  4276. if not NoSelect and ShouldExtend then
  4277. TextEnd {select to end}
  4278. else
  4279. SetCurPtr(CurPos.X,Delta.Y+Size.Y-1);
  4280. end;
  4281. procedure TCustomCodeEditor.JumpSelStart;
  4282. begin
  4283. if ValidBlock then
  4284. SetCurPtr(SelStart.X,SelStart.Y);
  4285. end;
  4286. procedure TCustomCodeEditor.JumpSelEnd;
  4287. begin
  4288. if ValidBlock then
  4289. SetCurPtr(SelEnd.X,SelEnd.Y);
  4290. end;
  4291. function TCustomCodeEditor.GetBookmark(MarkIdx: sw_integer):TEditorBookMark;
  4292. var LineNr : sw_integer;
  4293. begin
  4294. GetBookmark.Valid:=false;
  4295. if not (MarkIdx in [0..9]) then exit;
  4296. with Bookmarks[MarkIdx] do
  4297. if Valid=true then
  4298. begin
  4299. LineNr:=FindMarkLineNr(MarkIdx);
  4300. if LineNr>=0 then
  4301. Pos.Y:=LineNr
  4302. else
  4303. Valid:=false;
  4304. end;
  4305. GetBookmark:=Bookmarks[MarkIdx];
  4306. end;
  4307. procedure TCustomCodeEditor.SetBookmark(MarkIdx: sw_integer; ABookmark: TEditorBookMark);
  4308. var Line : PCustomLine;
  4309. begin
  4310. if not (MarkIdx in [0..9]) then exit;
  4311. Bookmarks[MarkIdx]:=ABookmark;
  4312. if ABookmark.Valid then
  4313. begin
  4314. {invalid Pos.Y will lead to crash check it beforehand }
  4315. if (ABookmark.Pos.X<0) or (ABookmark.Pos.X>MaxLineLength)
  4316. or (ABookmark.Pos.Y<0) or (ABookmark.Pos.Y>=GetLineCount) then
  4317. begin
  4318. Bookmarks[MarkIdx].Valid:=false;
  4319. exit;
  4320. end;
  4321. Line:=GetLine(ABookmark.Pos.Y);
  4322. if Assigned(Line) then
  4323. Line^.InsertMark(@Self,@Bookmarks[MarkIdx])
  4324. else
  4325. Bookmarks[MarkIdx].Valid:=false; {this should not be ever reached, but safty first}
  4326. end;
  4327. end;
  4328. function TCustomCodeEditor.FindMarkLineNr(MarkIdx: sw_integer):sw_integer;
  4329. var Count, CurLineNr, CurMarkNr : sw_integer;
  4330. Line : PCustomLine;
  4331. LI : PEditorLineInfo;
  4332. begin
  4333. Count:=GetLineCount;
  4334. FindMarkLineNr:=-1;
  4335. if Count>1 then
  4336. for CurLineNr:=0 to Count-1 do
  4337. begin
  4338. Line:=GetLine(CurLineNr);
  4339. if Assigned(Line) then LI:=Line^.GetEditorInfo(@Self) else LI:=nil;
  4340. if Assigned(LI) then
  4341. if Assigned(LI^.BookMarks) then
  4342. begin
  4343. CurMarkNr := LI^.BookMarks^.IndexOf(@Bookmarks[MarkIdx]);
  4344. if CurMarkNr>=0 then
  4345. begin
  4346. FindMarkLineNr:=CurLineNr;
  4347. break;
  4348. end;
  4349. end;
  4350. end;
  4351. end;
  4352. procedure TCustomCodeEditor.JumpMark(MarkIdx: integer);
  4353. var LineNr : sw_integer;
  4354. begin
  4355. if (MarkIdx<Low(Bookmarks)) or (MarkIdx>High(Bookmarks)) then
  4356. begin ErrorBox(FormatStrInt(msg_invalidmarkindex,MarkIdx),nil); Exit; end;
  4357. with Bookmarks[MarkIdx] do
  4358. if Valid=false then
  4359. InformationBox(FormatStrInt(msg_marknotset,MarkIdx),nil)
  4360. else
  4361. begin
  4362. DontConsiderShiftState:=true;
  4363. LineNr:=FindMarkLineNr(MarkIdx); {Find current marked line}
  4364. if LineNr>=0 then
  4365. SetCurPtr(Pos.X,LineNr)
  4366. else
  4367. InformationBox(FormatStrInt(msg_marknotset,MarkIdx),nil);
  4368. DontConsiderShiftState:=false;
  4369. end;
  4370. end;
  4371. procedure TCustomCodeEditor.DefineMark(MarkIdx: integer);
  4372. var Line : PCustomLine;
  4373. LI : PEditorLineInfo;
  4374. LineNr : sw_integer;
  4375. begin
  4376. if (MarkIdx<Low(Bookmarks)) or (MarkIdx>High(Bookmarks)) then
  4377. begin
  4378. ErrorBox(FormatStrInt(msg_invalidmarkindex,MarkIdx),nil);
  4379. Exit;
  4380. end;
  4381. if Bookmarks[MarkIdx].Valid then
  4382. begin
  4383. LineNr:=FindMarkLineNr(MarkIdx); {find current marked line}
  4384. if LineNr>=0 then
  4385. begin
  4386. Line:=GetLine(LineNr);
  4387. Line^.DeleteMark(@Self,@Bookmarks[MarkIdx]);
  4388. end;
  4389. end;
  4390. Line:=GetLine(CurPos.Y);
  4391. Line^.InsertMark(@Self,@Bookmarks[MarkIdx]);
  4392. with Bookmarks[MarkIdx] do
  4393. begin
  4394. Pos:=CurPos;
  4395. Valid:=true;
  4396. end;
  4397. end;
  4398. procedure TCustomCodeEditor.JumpToLastCursorPos;
  4399. begin
  4400. NotImplemented;
  4401. end;
  4402. procedure TCustomCodeEditor.UpperCase;
  4403. var StartP,EndP: TPoint;
  4404. begin
  4405. if ValidBlock=false then Exit;
  4406. GetSelectionArea(StartP,EndP);
  4407. AddGroupedAction(eaUpperCase);
  4408. ChangeCaseArea(StartP,EndP,caToUpperCase);
  4409. CloseGroupedAction(eaUpperCase);
  4410. end;
  4411. procedure TCustomCodeEditor.LowerCase;
  4412. var StartP,EndP: TPoint;
  4413. begin
  4414. if ValidBlock=false then Exit;
  4415. GetSelectionArea(StartP,EndP);
  4416. AddGroupedAction(eaLowerCase);
  4417. ChangeCaseArea(StartP,EndP,caToLowerCase);
  4418. CloseGroupedAction(eaLowerCase);
  4419. end;
  4420. procedure TCustomCodeEditor.ToggleCase;
  4421. var StartP,EndP: TPoint;
  4422. begin
  4423. if ValidBlock=false then Exit;
  4424. GetSelectionArea(StartP,EndP);
  4425. AddGroupedAction(eaToggleCase);
  4426. ChangeCaseArea(StartP,EndP,caToggleCase);
  4427. CloseGroupedAction(eaToggleCase);
  4428. end;
  4429. procedure TCustomCodeEditor.WordLowerCase;
  4430. var StartP,EndP: TPoint;
  4431. begin
  4432. if GetCurrentWordArea(StartP,EndP)=false then Exit;
  4433. AddGroupedAction(eaLowerCase);
  4434. ChangeCaseArea(StartP,EndP,caToLowerCase);
  4435. CloseGroupedAction(eaLowerCase);
  4436. end;
  4437. procedure TCustomCodeEditor.WordUpperCase;
  4438. var StartP,EndP: TPoint;
  4439. begin
  4440. if GetCurrentWordArea(StartP,EndP)=false then Exit;
  4441. AddGroupedAction(eaUpperCase);
  4442. ChangeCaseArea(StartP,EndP,caToUpperCase);
  4443. CloseGroupedAction(eaUpperCase);
  4444. end;
  4445. procedure TCustomCodeEditor.CreateFoldFromBlock;
  4446. var StartY,EndY: sw_integer;
  4447. begin
  4448. if not IsFlagSet(efFolds) then Exit;
  4449. if not ValidBlock then Exit;
  4450. StartY:=SelStart.Y; EndY:=SelEnd.Y;
  4451. if SelEnd.X=0 then Dec(EndY);
  4452. if CreateFold(StartY,EndY,false)=false then
  4453. ErrorBox(msg_foldboundsarenotvalid,nil);
  4454. end;
  4455. procedure TCustomCodeEditor.ToggleFold;
  4456. var F: PFold;
  4457. begin
  4458. if not IsFlagSet(efFolds) then Exit;
  4459. F:=GetLineFold(CurPos.Y);
  4460. if Assigned(F) then
  4461. F^.Collapse(not F^.Collapsed_);
  4462. end;
  4463. procedure TCustomCodeEditor.ExpandFold;
  4464. var F: PFold;
  4465. begin
  4466. if not IsFlagSet(efFolds) then Exit;
  4467. F:=GetLineFold(CurPos.Y);
  4468. if Assigned(F) then
  4469. F^.Collapse(false);
  4470. end;
  4471. procedure TCustomCodeEditor.CollapseFold;
  4472. var F: PFold;
  4473. begin
  4474. if not IsFlagSet(efFolds) then Exit;
  4475. F:=GetLineFold(CurPos.Y);
  4476. if Assigned(F) then
  4477. F^.Collapse(true);
  4478. end;
  4479. procedure TCustomCodeEditor.ChangeCaseArea(StartP,EndP: TPoint; CaseAction: TCaseAction);
  4480. var Y,X: sw_integer;
  4481. X1,X2: sw_integer;
  4482. S: sw_astring;
  4483. C: AnsiChar;
  4484. StartPos : TPoint;
  4485. HoldUndo : boolean;
  4486. begin
  4487. Lock;
  4488. HoldUndo:=GetStoreUndo;
  4489. SetStoreUndo(false);
  4490. for Y:=StartP.Y to EndP.Y do
  4491. begin
  4492. S:=GetDisplayText(Y);
  4493. { Pierre, please implement undo here! Gabor }
  4494. X1:=0; X2:=length(S)-1;
  4495. if Y=StartP.Y then X1:=StartP.X;
  4496. if Y=EndP.Y then X2:=EndP.X;
  4497. SetStoreUndo(HoldUndo);
  4498. StartPos.X:=X1;
  4499. StartPos.Y:=Y;
  4500. { the only drawback is that we keep
  4501. the original text even if Toggle where
  4502. it is not really necessary PM }
  4503. Addaction(eaOverwriteText,StartPos,StartPos,Copy(S,X1+1,X2-X1+1),GetFlags);
  4504. SetStoreUndo(false);
  4505. for X:=X1 to X2 do
  4506. begin
  4507. C:=S[X+1];
  4508. case CaseAction of
  4509. caToLowerCase : C:=LowCase(C);
  4510. caToUpperCase : C:=UpCase(C);
  4511. caToggleCase : if C in['a'..'z'] then
  4512. C:=Upcase(C)
  4513. else
  4514. C:=LowCase(C);
  4515. end;
  4516. S[X+1]:=C;
  4517. end;
  4518. SetDisplayText(Y,S);
  4519. end;
  4520. UpdateAttrsRange(StartP.Y,EndP.Y,attrAll);
  4521. DrawLines(CurPos.Y);
  4522. SetModified(true);
  4523. Addaction(eaMoveCursor,StartPos,CurPos,'',GetFlags);
  4524. SetStoreUndo(HoldUndo);
  4525. UnLock;
  4526. end;
  4527. procedure TCustomCodeEditor.PushInfo(Const st : string);
  4528. begin
  4529. { Dummies }
  4530. end;
  4531. procedure TCustomCodeEditor.PopInfo;
  4532. begin
  4533. { Dummies }
  4534. end;
  4535. procedure TCustomCodeEditor.InsertOptions;
  4536. begin
  4537. { Abstract }
  4538. NotImplemented;
  4539. end;
  4540. function TCustomCodeEditor.GetLineFold(EditorLine: sw_integer): PFold;
  4541. var L: PCustomLine;
  4542. LI: PEditorLineInfo;
  4543. F: PFold;
  4544. begin
  4545. F:=nil;
  4546. if IsFlagSet(efFolds) then
  4547. if (0<=EditorLine) and (EditorLine<GetLineCount) then
  4548. begin
  4549. L:=GetLine(EditorLine);
  4550. if Assigned(L) then
  4551. LI:=L^.GetEditorInfo(@Self)
  4552. else
  4553. LI:=nil;
  4554. if Assigned(LI) then
  4555. F:=LI^.Fold;
  4556. end;
  4557. GetLineFold:=F;
  4558. end;
  4559. function TCustomCodeEditor.IsLineVisible(EditorLine: sw_integer): boolean;
  4560. var V: boolean;
  4561. F,PrevF: PFold;
  4562. FoldHeadline: boolean;
  4563. begin
  4564. V:=true;
  4565. if IsFlagSet(efFolds) then
  4566. begin
  4567. F:=GetLineFold(EditorLine);
  4568. if Assigned(F) then
  4569. begin
  4570. PrevF:=GetLineFold(EditorLine-1);
  4571. FoldHeadline:=false;
  4572. if (PrevF<>F) and ((PrevF=nil) or (not PrevF^.IsParent(F))) then
  4573. FoldHeadline:=true;
  4574. if FoldHeadline then
  4575. begin
  4576. if Assigned(F^.ParentFold) and (F^.ParentFold^.IsCollapsed) then
  4577. V:=false;
  4578. end
  4579. else
  4580. if F^.IsCollapsed then
  4581. V:=false;
  4582. end;
  4583. end;
  4584. IsLineVisible:=V;
  4585. end;
  4586. function TCustomCodeEditor.ViewToEditorLine(ViewLine: sw_integer): sw_integer;
  4587. var I,Line,Count: sw_integer;
  4588. begin
  4589. if not IsFlagSet(efFolds) then
  4590. Line:=ViewLine
  4591. else
  4592. begin
  4593. Count:=GetLineCount;
  4594. I:=0; Line:=-1;
  4595. while (Line<ViewLine) and (I<Count) do
  4596. begin
  4597. if IsLineVisible(I) then
  4598. Inc(Line);
  4599. Inc(I);
  4600. end;
  4601. if Line<>ViewLine then
  4602. Line:=-1
  4603. else
  4604. Line:=I-1;
  4605. end;
  4606. ViewToEditorLine:=Line;
  4607. end;
  4608. function TCustomCodeEditor.EditorToViewLine(EditorLine: sw_integer): sw_integer;
  4609. var I,Line: sw_integer;
  4610. begin
  4611. if not IsFlagSet(efFolds) then
  4612. Line:=EditorLine
  4613. else
  4614. begin
  4615. Line:=-1;
  4616. for I:=0 to EditorLine do
  4617. if IsLineVisible(I) then
  4618. Inc(Line);
  4619. end;
  4620. EditorToViewLine:=Line;
  4621. end;
  4622. procedure TCustomCodeEditor.ViewToEditorPoint(P: TPoint; var NP: TPoint);
  4623. begin
  4624. NP.X:=P.X-GetReservedColCount;
  4625. NP.Y:=ViewToEditorLine(P.Y);
  4626. end;
  4627. procedure TCustomCodeEditor.EditorToViewPoint(P: TPoint; var NP: TPoint);
  4628. begin
  4629. NP.X:=P.X+GetReservedColCount;
  4630. NP.Y:=EditorToViewLine(P.Y);
  4631. end;
  4632. procedure TCustomCodeEditor.FindMatchingDelimiter(ScanForward: boolean);
  4633. const OpenSymbols : string[6] = '[{(<''"';
  4634. CloseSymbols : string[6] = ']})>''"';
  4635. var SymIdx: integer;
  4636. LineText,LineAttr: sw_astring;
  4637. CurChar: AnsiChar;
  4638. X,Y: sw_integer;
  4639. LineCount: sw_integer;
  4640. JumpPos: TPoint;
  4641. BracketLevel: integer;
  4642. begin
  4643. JumpPos.X:=-1; JumpPos.Y:=-1;
  4644. LineText:=GetDisplayText(CurPos.Y);
  4645. LineText:=copy(LineText,CurPos.X+1,1);
  4646. if LineText='' then Exit;
  4647. CurChar:=LineText[1];
  4648. Y:=CurPos.Y; X:=CurPos.X; LineCount:=0;
  4649. BracketLevel:=1;
  4650. if ScanForward then
  4651. begin
  4652. SymIdx:=Pos(CurChar,OpenSymbols);
  4653. if SymIdx=0 then Exit;
  4654. repeat
  4655. Inc(LineCount);
  4656. GetDisplayTextFormat(Y,LineText,LineAttr);
  4657. if LineCount<>1 then X:=-1;
  4658. repeat
  4659. Inc(X);
  4660. if X<length(LineText) then
  4661. if copy(LineAttr,X+1,1)<>chr(attrComment) then
  4662. if (LineText[X+1]=CloseSymbols[SymIdx]) and (BracketLevel=1) then
  4663. begin
  4664. JumpPos.X:=X; JumpPos.Y:=Y;
  4665. end
  4666. else
  4667. if LineText[X+1]=OpenSymbols[SymIdx] then
  4668. Inc(BracketLevel)
  4669. else
  4670. if LineText[X+1]=CloseSymbols[SymIdx] then
  4671. if BracketLevel>1 then
  4672. Dec(BracketLevel);
  4673. until (X>=length(LineText)) or (JumpPos.X<>-1);
  4674. Inc(Y);
  4675. until (Y>=GetLineCount) or (JumpPos.X<>-1);
  4676. end
  4677. else
  4678. begin
  4679. SymIdx:=Pos(CurChar,CloseSymbols);
  4680. if SymIdx=0 then Exit;
  4681. repeat
  4682. Inc(LineCount);
  4683. GetDisplayTextFormat(Y,LineText,LineAttr);
  4684. if LineCount<>1 then X:=length(LineText);
  4685. repeat
  4686. Dec(X);
  4687. if X>0 then
  4688. if copy(LineAttr,X+1,1)<>chr(attrComment) then
  4689. if (LineText[X+1]=OpenSymbols[SymIdx]) and (BracketLevel=1) then
  4690. begin
  4691. JumpPos.X:=X; JumpPos.Y:=Y;
  4692. end
  4693. else
  4694. if LineText[X+1]=CloseSymbols[SymIdx] then
  4695. Inc(BracketLevel)
  4696. else
  4697. if LineText[X+1]=OpenSymbols[SymIdx] then
  4698. if BracketLevel>1 then
  4699. Dec(BracketLevel);
  4700. until (X<0) or (JumpPos.X<>-1);
  4701. Dec(Y);
  4702. until (Y<0) or (JumpPos.X<>-1);
  4703. end;
  4704. if JumpPos.X<>-1 then
  4705. begin
  4706. SetCurPtr(JumpPos.X,JumpPos.Y);
  4707. TrackCursor(do_centre);
  4708. end;
  4709. end;
  4710. function TCustomCodeEditor.InsertNewLine: Sw_integer;
  4711. var i,Ind: Sw_integer;
  4712. S,IndentStr: Sw_astring;
  4713. procedure CalcIndent(LineOver: Sw_integer);
  4714. begin
  4715. if (LineOver<0) or (LineOver>GetLineCount) or ((GetFlags and efNoIndent)<>0) then
  4716. Ind:=0 else
  4717. begin
  4718. repeat
  4719. IndentStr:=GetDisplayText(LineOver);
  4720. Dec(LineOver);
  4721. until (LineOver<0) or (IndentStr<>'');
  4722. Ind:=0;
  4723. while (Ind<length(IndentStr)) and (IndentStr[Ind+1]=' ') do
  4724. Inc(Ind);
  4725. end;
  4726. IndentStr:=CharStr(' ',Ind);
  4727. end;
  4728. var {SelBack: sw_integer;}
  4729. SCP: TPoint;
  4730. CI : sw_integer;
  4731. HoldUndo : Boolean;
  4732. L,NewL: PCustomLine;
  4733. EI,NewEI: PEditorLineInfo;
  4734. begin
  4735. if IsReadOnly then begin InsertNewLine:=-1; Exit; end;
  4736. Lock;
  4737. SCP:=CurPos;
  4738. HoldUndo:=GetStoreUndo;
  4739. SetStoreUndo(false);
  4740. if CurPos.Y<GetLineCount then S:=GetLineText(CurPos.Y) else S:='';
  4741. if Overwrite=false then
  4742. begin
  4743. if CurPos.Y<GetLineCount then
  4744. begin
  4745. L:=GetLine(CurPos.Y);
  4746. if not assigned(L) then
  4747. EI:=nil
  4748. else
  4749. EI:=L^.GetEditorInfo(@Self);
  4750. end
  4751. else
  4752. EI:=nil;
  4753. { SelBack:=0;}
  4754. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  4755. if GetLineCount>0 then
  4756. begin
  4757. S:=GetLineText(CurPos.Y);
  4758. { SelBack:=length(S)-SelEnd.X;}
  4759. SetLineText(CurPos.Y,RTrim(S,not IsFlagSet(efUseTabCharacters)));
  4760. end;
  4761. SetLineText(CurPos.Y,copy(S,1,CI-1));
  4762. CalcIndent(CurPos.Y);
  4763. S:=copy(S,CI,Length(S));
  4764. i:=1;
  4765. while (i<=length(s)) and (i<=length(IndentStr)) and (s[i]=' ') do
  4766. inc(i);
  4767. if i>1 then
  4768. Delete(IndentStr,1,i-1);
  4769. NewL:=InsertLine(CurPos.Y+1,IndentStr+S);
  4770. LimitsChanged;
  4771. (* if PointOfs(SelStart)<>PointOfs(SelEnd) then { !!! check it - it's buggy !!! }
  4772. begin SelEnd.Y:=CurPos.Y+1; SelEnd.X:=length(GetLineText(CurPos.Y+1))-SelBack; end;*)
  4773. UpdateAttrs(CurPos.Y,attrAll);
  4774. AdjustBookMark(CurPos.X,Ind,CurPos.Y,CurPos.Y+1);
  4775. SetCurPtr(Ind,CurPos.Y+1);
  4776. NewEI:=NewL^.GetEditorInfo(@Self);
  4777. if Assigned(EI) and Assigned(NewEI) then
  4778. begin
  4779. NewEI^.SetFold(EI^.Fold);
  4780. if Assigned(EI^.Fold) then
  4781. if EI^.Fold^.IsCollapsed then
  4782. EI^.Fold^.Collapse(false);
  4783. end;
  4784. SetStoreUndo(HoldUndo);
  4785. { obsolete IndentStr is taken care of by the Flags PM }
  4786. Addaction(eaInsertLine,SCP,CurPos,CharStr(' ',i-1){IndentStr},GetFlags);
  4787. SetStoreUndo(false);
  4788. AdjustSelectionPos(SCP.X,SCP.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
  4789. end else
  4790. begin
  4791. CalcIndent(CurPos.Y);
  4792. if CurPos.Y=GetLineCount-1 then
  4793. begin
  4794. AddLine(IndentStr);
  4795. AdjustSelectionBefore(0,1);
  4796. LimitsChanged;
  4797. SetStoreUndo(HoldUndo);
  4798. UpdateAttrs(CurPos.Y,attrAll);
  4799. AdjustBookMark(CurPos.X,Ind,CurPos.Y,CurPos.Y+1);
  4800. SetCurPtr(Ind,CurPos.Y+1);
  4801. { obsolete IndentStr is taken care of by the Flags PM }
  4802. Addaction(eaInsertLine,SCP,CurPos,''{IndentStr},GetFlags);
  4803. SetStoreUndo(false);
  4804. end
  4805. else
  4806. begin
  4807. UpdateAttrs(CurPos.Y,attrAll);
  4808. SetStoreUndo(HoldUndo);
  4809. AdjustBookMark(CurPos.X,Ind,CurPos.Y,CurPos.Y+1);
  4810. SetCurPtr(Ind,CurPos.Y+1);
  4811. AddAction(eaMoveCursor,SCP,CurPos,'',GetFlags);
  4812. SetStoreUndo(false);
  4813. end;
  4814. end;
  4815. DrawLines(CurPos.Y);
  4816. SetStoreUndo(HoldUndo);
  4817. SetModified(true);
  4818. Unlock;
  4819. end;
  4820. procedure TCustomCodeEditor.BreakLine;
  4821. var
  4822. SCP: TPoint;
  4823. begin
  4824. { Like insert new line, but leave current pos unchanged }
  4825. SCP:=CurPos;
  4826. InsertNewLine;
  4827. SetCurPtr(SCP.X,SCP.Y);
  4828. end;
  4829. procedure TCustomCodeEditor.BackSpace;
  4830. var S,PreS: sw_astring;
  4831. OI,CI,CP,Y,TX: Sw_integer;
  4832. SCP,SC1 : TPoint;
  4833. HoldUndo : Boolean;
  4834. begin
  4835. if IsReadOnly then Exit;
  4836. Lock;
  4837. SCP:=CurPos;
  4838. HoldUndo:=GetStoreUndo;
  4839. SetStoreUndo(false);
  4840. if CurPos.X=0 then
  4841. begin
  4842. if CurPos.Y>0 then
  4843. begin
  4844. CI:=Length(GetDisplayText(CurPos.Y-1));
  4845. AdjustBookMark(0,CI,CurPos.Y,CurPos.Y-1);
  4846. S:=GetLineText(CurPos.Y-1);
  4847. SetLineText(CurPos.Y-1,S+GetLineText(CurPos.Y));
  4848. SC1.X:=Length(S);SC1.Y:=CurPOS.Y-1;
  4849. SetStoreUndo(HoldUndo);
  4850. AddAction(eaDeleteLine,SCP,SC1,GetLineText(CurPos.Y),GetFlags);
  4851. SetStoreUndo(false);
  4852. DeleteLine(CurPos.Y);
  4853. LimitsChanged;
  4854. SetCurPtr(CI,CurPos.Y-1);
  4855. AdjustSelectionPos(Ci,CurPos.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
  4856. end;
  4857. end
  4858. else
  4859. begin
  4860. CP:=CurPos.X-1;
  4861. S:=GetLineText(CurPos.Y);
  4862. CI:=LinePosToCharIdx(CurPos.Y,CP);
  4863. if (ci>0) and (ci<=length(S)) then
  4864. if (s[ci]=TAB) {and (CharIdxToLinePos(Curpos.y,ci)=cp)} then
  4865. CP:=CharIdxToLinePos(CurPos.Y,CI);
  4866. if IsFlagSet(efBackspaceUnindents) then
  4867. begin
  4868. S:=GetDisplayText(CurPos.Y);
  4869. if Trim(copy(S,1,CP+1))='' then
  4870. begin
  4871. Y:=CurPos.Y;
  4872. while (Y>0) do
  4873. begin
  4874. Dec(Y);
  4875. PreS:=GetDisplayText(Y);
  4876. if Trim(copy(PreS,1,CP+1))<>'' then Break;
  4877. end;
  4878. if Y<0 then PreS:='';
  4879. TX:=0;
  4880. while (TX<length(PreS)) and (PreS[TX+1]=' ') do
  4881. Inc(TX);
  4882. if TX<CP then CP:=TX;
  4883. end;
  4884. end;
  4885. S:=GetLineText(CurPos.Y);
  4886. OI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  4887. CI:=LinePosToCharIdx(CurPos.Y,CP);
  4888. SetLineText(CurPos.Y,copy(S,1,CI-1)+copy(S,OI,Length(S)));
  4889. SetCurPtr(CP,CurPos.Y);
  4890. SetStoreUndo(HoldUndo);
  4891. Addaction(eaDeleteText,SCP,CurPos,Copy(S,CI,OI-CI),GetFlags);
  4892. SetStoreUndo(false);
  4893. AdjustSelectionPos(SCP.X-1,SCP.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
  4894. end;
  4895. UpdateAttrs(CurPos.Y,attrAll);
  4896. DrawLines(CurPos.Y);
  4897. SetStoreUndo(HoldUndo);
  4898. SetModified(true);
  4899. Unlock;
  4900. end;
  4901. procedure TCustomCodeEditor.DelChar;
  4902. var S: sw_astring;
  4903. SDX,SDY,CI : sw_integer;
  4904. HoldUndo : boolean;
  4905. SCP : TPoint;
  4906. begin
  4907. if IsReadOnly then Exit;
  4908. Lock;
  4909. HoldUndo:=GetStoreUndo;
  4910. SetStoreUndo(false);
  4911. S:=GetLineText(CurPos.Y);
  4912. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  4913. if (CI>length(S)) or (S='') then
  4914. begin
  4915. if CurPos.Y<GetLineCount-1 then
  4916. begin
  4917. SetLineText(CurPos.Y,S+CharStr(' ',CurPOS.X-Length(S))+GetLineText(CurPos.Y+1));
  4918. AdjustBookMark(0,CurPos.X,CurPos.Y+1,CurPos.Y);
  4919. SDX:=CurPos.X;
  4920. SetStoreUndo(HoldUndo);
  4921. SCP.X:=0;SCP.Y:=CurPos.Y+1;
  4922. AddGroupedAction(eaDelChar);
  4923. AddAction(eaMoveCursor,CurPos,SCP,'',GetFlags);
  4924. S:=GetLineText(CurPos.Y+1);
  4925. AddAction(eaDeleteLine,SCP,CurPos,S,GetFlags);
  4926. CloseGroupedAction(eaDelChar);
  4927. SetStoreUndo(false);
  4928. DeleteLine(CurPos.Y+1);
  4929. LimitsChanged;
  4930. SDY:=-1;
  4931. SetCurPtr(CurPos.X,CurPos.Y);
  4932. UpdateAttrs(CurPos.Y,attrAll);
  4933. AdjustSelectionPos(CurPos.X,CurPos.Y,SDX,SDY);
  4934. end;
  4935. end
  4936. else
  4937. begin
  4938. SCP:=CurPos;
  4939. { Problem if S[CurPos.X+1]=TAB !! PM }
  4940. if S[CI]=TAB then
  4941. begin
  4942. { we want to remove the tab if we are at the first place
  4943. of the tab, but the following test was true for the last position
  4944. in tab
  4945. if CharIdxToLinePos(Curpos.y,ci)=Curpos.x then }
  4946. if CharIdxToLinePos(Curpos.y,ci-1)=Curpos.x-1 then
  4947. Delete(S,Ci,1)
  4948. else
  4949. S:=Copy(S,1,CI-1)+CharStr(' ',GetTabSize-1)+Copy(S,CI+1,Length(S));
  4950. SetStoreUndo(HoldUndo);
  4951. Addaction(eaDeleteText,CurPos,CurPos,#9,GetFlags);
  4952. SDX:=-1;
  4953. SetStoreUndo(false);
  4954. end
  4955. else
  4956. begin
  4957. SetStoreUndo(HoldUndo);
  4958. Addaction(eaDeleteText,CurPos,CurPos,S[CI],GetFlags);
  4959. SetStoreUndo(false);
  4960. SDX:=-1;
  4961. Delete(S,CI,1);
  4962. end;
  4963. SetLineText(CurPos.Y,S);
  4964. SDY:=0;
  4965. SetCurPtr(CurPos.X,CurPos.Y);
  4966. UpdateAttrs(CurPos.Y,attrAll);
  4967. AdjustSelectionPos(SCP.X,SCP.Y,SDX,SDY);
  4968. end;
  4969. DrawLines(CurPos.Y);
  4970. SetStoreUndo(HoldUndo);
  4971. SetModified(true);
  4972. Unlock;
  4973. end;
  4974. procedure TCustomCodeEditor.DelWord;
  4975. var
  4976. SP,EP : TPoint;
  4977. SelSize : sw_integer;
  4978. begin
  4979. if IsReadOnly then Exit;
  4980. Lock;
  4981. SP:=SelStart;
  4982. EP:=SelEnd;
  4983. SetSelection(SelStart,SelStart);
  4984. SelectWord;
  4985. SelSize:=SelEnd.X-SelStart.X;
  4986. DelSelect;
  4987. SetSelection(SP,EP);
  4988. AdjustSelectionPos(CurPos.X,CurPos.Y,-SelSize,0);
  4989. if SelSize>0 then
  4990. SetModified(true);
  4991. Unlock;
  4992. end;
  4993. procedure TCustomCodeEditor.DelToEndOfWord;
  4994. var
  4995. SP,EP : TPoint;
  4996. S : String;
  4997. SelSize : sw_integer;
  4998. begin
  4999. if IsReadOnly then Exit;
  5000. Lock;
  5001. SP:=SelStart;
  5002. EP:=SelEnd;
  5003. SetSelection(SelStart,SelStart);
  5004. SelectWord;
  5005. S:=GetDisplayText(CurPos.Y);
  5006. if ((SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y)) then
  5007. begin
  5008. if (Length(S) <= CurPos.X) then
  5009. begin
  5010. SetSelection(SP,EP);
  5011. DelChar;
  5012. Unlock;
  5013. exit;
  5014. end
  5015. else
  5016. begin
  5017. SelEnd.X:=CurPos.X+1;
  5018. SelEnd.Y:=CurPos.Y;
  5019. end;
  5020. end;
  5021. while (length(S)>= SelEnd.X+1) and
  5022. ((S[SelEnd.X+1]=' ') or (S[SelEnd.X+1]=TAB)) do
  5023. inc(SelEnd.X);
  5024. SetSelection(CurPos,SelEnd);
  5025. SelSize:=SelEnd.X-SelStart.X;
  5026. DelSelect;
  5027. SetSelection(SP,EP);
  5028. AdjustSelectionPos(CurPos.X,CurPos.Y,-SelSize,0);
  5029. if SelSize>0 then
  5030. SetModified(true);
  5031. Unlock;
  5032. end;
  5033. procedure TCustomCodeEditor.DelStart;
  5034. var S: sw_astring;
  5035. OI: Sw_integer;
  5036. HoldUndo : Boolean;
  5037. SCP : TPoint;
  5038. begin
  5039. if IsReadOnly then Exit;
  5040. Lock;
  5041. HoldUndo:=GetStoreUndo;
  5042. SetStoreUndo(false);
  5043. SCP:=CurPos;
  5044. S:=GetLineText(CurPos.Y);
  5045. if (S<>'') and (CurPos.X<>0) then
  5046. begin
  5047. OI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  5048. SetLineText(CurPos.Y,copy(S,OI,Length(S)));
  5049. SetCurPtr(0,CurPos.Y);
  5050. SetStoreUndo(HoldUndo);
  5051. Addaction(eaDeleteText,SCP,CurPos,copy(S,1,OI-1),GetFlags);
  5052. SetStoreUndo(false);
  5053. AdjustSelectionPos(CurPos.X,CurPos.Y,-length(copy(S,1,OI-1)),0);
  5054. UpdateAttrs(CurPos.Y,attrAll);
  5055. DrawLines(CurPos.Y);
  5056. SetModified(true);
  5057. end;
  5058. SetStoreUndo(HoldUndo);
  5059. Unlock;
  5060. end;
  5061. procedure TCustomCodeEditor.DelEnd;
  5062. var S: sw_astring;
  5063. OI: Sw_integer;
  5064. HoldUndo : Boolean;
  5065. SCP : TPoint;
  5066. begin
  5067. if IsReadOnly then Exit;
  5068. Lock;
  5069. HoldUndo:=GetStoreUndo;
  5070. SetStoreUndo(false);
  5071. SCP:=CurPos;
  5072. S:=GetLineText(CurPos.Y);
  5073. if (S<>'') and (CurPos.X<>length(S)) then
  5074. begin
  5075. OI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  5076. SetLineText(CurPos.Y,copy(S,1,OI-1));
  5077. SetCurPtr(CurPos.X,CurPos.Y);
  5078. SetStoreUndo(HoldUndo);
  5079. Addaction(eaDeleteText,SCP,CurPos,copy(S,OI,Length(S)),GetFlags);
  5080. SetStoreUndo(false);
  5081. AdjustSelectionPos(CurPos.X+1,CurPos.Y,-length(copy(S,OI,Length(S)))+1,0);
  5082. UpdateAttrs(CurPos.Y,attrAll);
  5083. DrawLines(CurPos.Y);
  5084. SetModified(true);
  5085. end;
  5086. SetStoreUndo(HoldUndo);
  5087. Unlock;
  5088. end;
  5089. procedure TCustomCodeEditor.DelLine;
  5090. var
  5091. HoldUndo : boolean;
  5092. SP : TPoint;
  5093. S : Sw_AString;
  5094. begin
  5095. if IsReadOnly then Exit;
  5096. Lock;
  5097. if GetLineCount>0 then
  5098. begin
  5099. SP:=CurPos;
  5100. S:=GetLineText(CurPos.Y);
  5101. HoldUndo:=GetStoreUndo;
  5102. SetStoreUndo(false);
  5103. DeleteLine(CurPos.Y);
  5104. LimitsChanged;
  5105. AdjustSelectionBefore(0,-1);
  5106. SetCurPtr(0,CurPos.Y);
  5107. UpdateAttrs(Max(0,CurPos.Y-1),attrAll);
  5108. DrawLines(CurPos.Y);
  5109. SetStoreUndo(HoldUndo);
  5110. AddAction(eaDeleteLine,SP,CurPos,S,GetFlags);
  5111. SetModified(true);
  5112. end;
  5113. Unlock;
  5114. end;
  5115. procedure TCustomCodeEditor.InsMode;
  5116. begin
  5117. SetInsertMode(Overwrite);
  5118. end;
  5119. function TCustomCodeEditor.GetCurrentWordArea(var StartP,EndP: TPoint): boolean;
  5120. const WordChars = ['A'..'Z','a'..'z','0'..'9','_'];
  5121. var P : TPoint;
  5122. S : Sw_AString;
  5123. StartPos,EndPos : sw_integer;
  5124. OK: boolean;
  5125. begin
  5126. P:=CurPos;
  5127. S:=GetLineText(P.Y);
  5128. StartPos:=P.X+1;
  5129. EndPos:=StartPos;
  5130. Ok:=false;
  5131. if Length(S)>=StartPos then
  5132. OK:=(S[StartPos] in WordChars);
  5133. if OK then
  5134. begin
  5135. While (StartPos>1) and (S[StartPos-1] in WordChars) do
  5136. Dec(StartPos);
  5137. While (EndPos<Length(S)) and (S[EndPos+1] in WordChars) do
  5138. Inc(EndPos);
  5139. StartP.X:=StartPos-1; StartP.Y:=CurPos.Y;
  5140. EndP.X:=EndPos-1; EndP.Y:=CurPos.Y;
  5141. end;
  5142. GetCurrentWordArea:=OK;
  5143. end;
  5144. function TCustomCodeEditor.GetCurrentWord : string;
  5145. var S: sw_astring;
  5146. StartP,EndP: TPoint;
  5147. begin
  5148. if GetCurrentWordArea(StartP,EndP)=false then
  5149. S:=''
  5150. else
  5151. begin
  5152. S:=GetLineText(StartP.Y);
  5153. S:=copy(S,StartP.X+1,EndP.X-StartP.X+1);
  5154. end;
  5155. GetCurrentWord:=S; {Note: AnsiString to ShortString convertion}
  5156. end;
  5157. procedure TCustomCodeEditor.StartSelect;
  5158. var P1,P2: TPoint;
  5159. begin
  5160. if ValidBlock=false then
  5161. begin
  5162. { SetSelection(SelStart,Limit);}
  5163. P1:=CurPos; P2:=CurPos; {P2.X:=length(GetLineText(P2.Y))+1;}
  5164. SetSelection(P1,P2);
  5165. end
  5166. else
  5167. SetSelection(CurPos,SelEnd);
  5168. if PointOfs(SelEnd)<PointOfs(SelStart) then
  5169. SetSelection(SelStart,SelStart);
  5170. CheckSels;
  5171. DrawView;
  5172. end;
  5173. procedure TCustomCodeEditor.EndSelect;
  5174. var P: TPoint;
  5175. LS: sw_integer;
  5176. begin
  5177. P:=CurPos;
  5178. { P.X:=Min(SelEnd.X,length(GetLineText(SelEnd.Y)));}
  5179. LS:=length(GetLineText(SelEnd.Y));
  5180. if LS<P.X then P.X:=LS;
  5181. CheckSels;
  5182. SetSelection(SelStart,P);
  5183. DrawView;
  5184. end;
  5185. procedure TCustomCodeEditor.DelSelect;
  5186. var LineDelta, LineCount, CurLine: Sw_integer;
  5187. StartX,EndX,LastX: Sw_integer;
  5188. S,Z: sw_astring;
  5189. SPos : TPoint;
  5190. begin
  5191. if IsReadOnly or (ValidBlock=false) then Exit;
  5192. Lock;
  5193. AddGroupedAction(eaDelBlock);
  5194. LineCount:=(SelEnd.Y-SelStart.Y)+1;
  5195. LineDelta:=0; LastX:=CurPos.X;
  5196. CurLine:=SelStart.Y;
  5197. { single line : easy }
  5198. if LineCount=1 then
  5199. begin
  5200. S:=GetDisplayText(CurLine);
  5201. StartX:=SelStart.X;
  5202. EndX:=SelEnd.X;
  5203. SetDisplayText(CurLine,RExpand(copy(S,1,StartX),StartX)
  5204. +copy(S,EndX+1,Length(S)));
  5205. if GetStoreUndo then
  5206. begin
  5207. SPos.X:=StartX;
  5208. SPos.Y:=CurLine;
  5209. AddAction(eaDeleteText,SPos,SPos,Copy(S,StartX+1,EndX-StartX),GetFlags);
  5210. end;
  5211. Inc(CurLine);
  5212. LastX:=SelStart.X;
  5213. end
  5214. { several lines : a bit less easy }
  5215. else
  5216. begin
  5217. S:=GetDisplayText(CurLine);
  5218. StartX:=SelStart.X;
  5219. EndX:=SelEnd.X;
  5220. Z:=GetDisplayText(CurLine+LineCount-1);
  5221. SetDisplayText(CurLine,RExpand(copy(S,1,StartX),StartX)
  5222. +copy(Z,EndX+1,Length(Z)));
  5223. if GetStoreUndo then
  5224. begin
  5225. SPos.X:=StartX;
  5226. SPos.Y:=CurLine;
  5227. AddAction(eaDeleteText,SPos,SPos,Copy(S,StartX+1,Length(S)),GetFlags);
  5228. S:=GetDisplayText(CurLine+LineCount-1);
  5229. end;
  5230. Inc(CurLine);
  5231. Inc(LineDelta);
  5232. LastX:=SelStart.X;
  5233. while (LineDelta<LineCount) do
  5234. begin
  5235. { delete the complete line }
  5236. DeleteLine(CurLine);
  5237. Inc(LineDelta);
  5238. end;
  5239. if GetStoreUndo then
  5240. begin
  5241. AddAction(eaInsertText,SPos,SPos,Copy(S,EndX+1,Length(S)),GetFlags);
  5242. end;
  5243. end;
  5244. HideSelect;
  5245. SetCurPtr(LastX,CurLine-1);
  5246. UpdateAttrs(CurPos.Y,attrAll);
  5247. DrawLines(CurPos.Y);
  5248. SetModified(true);
  5249. CloseGroupedAction(eaDelBlock);
  5250. UnLock;
  5251. end;
  5252. procedure TCustomCodeEditor.HideSelect;
  5253. begin
  5254. SetSelection(CurPos,CurPos);
  5255. DrawLines(Delta.Y);
  5256. end;
  5257. procedure TCustomCodeEditor.CopyBlock;
  5258. var Temp: PCodeEditor;
  5259. R: TRect;
  5260. begin
  5261. if IsReadOnly or (ValidBlock=false) then Exit;
  5262. Lock;
  5263. GetExtent(R);
  5264. AddGroupedAction(eaCopyBlock);
  5265. New(Temp, Init(R, nil, nil, nil,nil));
  5266. Temp^.InsertFrom(@Self);
  5267. (* Temp^.SelectAll(true);
  5268. { this selects one line too much because
  5269. we have a empty line at creation to avoid
  5270. negative line problems so we need to decrease SelEnd.Y }
  5271. Dec(Temp^.SelEnd.Y);*)
  5272. InsertFrom(Temp);
  5273. Dispose(Temp, Done);
  5274. CloseGroupedAction(eaCopyBlock);
  5275. UnLock;
  5276. end;
  5277. procedure TCustomCodeEditor.MoveBlock;
  5278. var Temp: PCodeEditor;
  5279. R: TRect;
  5280. OldPos: TPoint;
  5281. begin
  5282. if IsReadOnly then Exit;
  5283. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  5284. Lock;
  5285. AddGroupedAction(eaMoveBlock);
  5286. GetExtent(R);
  5287. New(Temp, Init(R, nil, nil, nil,nil));
  5288. Temp^.InsertFrom(@Self);
  5289. OldPos:=CurPos;
  5290. if CurPos.Y>SelStart.Y then
  5291. Dec(OldPos.Y,Temp^.GetLineCount-1);
  5292. DelSelect;
  5293. SetCurPtr(OldPos.X,OldPos.Y);
  5294. InsertFrom(Temp);
  5295. Dispose(Temp, Done);
  5296. CloseGroupedAction(eaMoveBlock);
  5297. UnLock;
  5298. end;
  5299. procedure TCustomCodeEditor.IndentBlock;
  5300. var
  5301. ey,i,Indlen : Sw_Integer;
  5302. S,Ind : Sw_AString;
  5303. Pos : Tpoint;
  5304. WasPersistentBlocks : boolean;
  5305. begin
  5306. if IsReadOnly then Exit;
  5307. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  5308. Lock;
  5309. AddGroupedAction(eaIndentBlock);
  5310. WasPersistentBlocks:=IsFlagSet(efPersistentBlocks);
  5311. if not WasPersistentBlocks then
  5312. SetFlags(GetFlags or efPersistentBlocks);
  5313. ey:=selend.y;
  5314. if selend.x=0 then
  5315. dec(ey);
  5316. S:='';
  5317. { If AutoIndent try to align first line to
  5318. last line before selection }
  5319. { DISABLED created problems PM
  5320. if IsFlagSet(efAutoIndent) and (SelStart.Y>0) then
  5321. begin
  5322. i:=SelStart.Y-1;
  5323. while (S='') and (i>=0) do
  5324. begin
  5325. S:=GetDisplayText(i);
  5326. dec(i);
  5327. end;
  5328. if (S='') or (S[1]<>' ') then
  5329. Ind:=' '
  5330. else
  5331. begin
  5332. i:=1;
  5333. while (i<=Length(S)) and (S[i]=' ') do
  5334. inc(i);
  5335. indlen:=i;
  5336. S:=GetDisplayText(SelStart.Y);
  5337. i:=1;
  5338. while (i<=Length(S)) and (S[i]=' ') do
  5339. inc(i);
  5340. indlen:=indlen-i;
  5341. if indlen<=0 then
  5342. indlen:=1;
  5343. Ind:=CharStr(' ',indlen);
  5344. end;
  5345. end
  5346. else
  5347. Ind:=' ';}
  5348. Indlen:=GetIndentSize;
  5349. {selection Start and End move along}
  5350. if SelStart.X>0 then inc(SelStart.X,Indlen);
  5351. if SelEnd.X>0 then inc(SelEnd.X,Indlen);
  5352. Ind:=CharStr(' ',Indlen);
  5353. for i:=selstart.y to ey do
  5354. begin
  5355. S:=GetLineText(i);
  5356. SetLineText(i,Ind+S);
  5357. Pos.X:=0;Pos.Y:=i;
  5358. AddAction(eaInsertText,Pos,Pos,Ind,GetFlags);
  5359. end;
  5360. SetCurPtr(CurPos.X,CurPos.Y);
  5361. {after SetCurPtr return PersistentBlocks as it was before}
  5362. if not WasPersistentBlocks then
  5363. SetFlags(GetFlags and (not longword(efPersistentBlocks)));
  5364. { must be added manually here PM }
  5365. AddAction(eaMoveCursor,Pos,CurPos,'',GetFlags);
  5366. UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
  5367. DrawLines(CurPos.Y);
  5368. SetModified(true);
  5369. CloseGroupedAction(eaIndentBlock);
  5370. UnLock;
  5371. end;
  5372. procedure TCustomCodeEditor.UnindentBlock;
  5373. var
  5374. ey,i,j,k,indlen : Sw_integer;
  5375. S : Sw_AString;
  5376. Pos : TPoint;
  5377. WasPersistentBlocks : boolean;
  5378. begin
  5379. if IsReadOnly then Exit;
  5380. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  5381. Lock;
  5382. AddGroupedAction(eaUnindentBlock);
  5383. WasPersistentBlocks:=IsFlagSet(efPersistentBlocks);
  5384. if not WasPersistentBlocks then
  5385. SetFlags(GetFlags or efPersistentBlocks);
  5386. ey:=selend.y;
  5387. if selend.x=0 then
  5388. dec(ey);
  5389. { If AutoIndent try to align first line to
  5390. last line before selection }
  5391. { Disabled created problems
  5392. if IsFlagSet(efAutoIndent) and (SelStart.Y>0) then
  5393. begin
  5394. S:=GetDisplayText(SelStart.Y);
  5395. i:=1;
  5396. while (i<=Length(S)) and (S[i]=' ') do
  5397. inc(i);
  5398. indlen:=i-1;
  5399. i:=SelStart.Y-1;
  5400. S:='';
  5401. while (S='') and (i>=0) do
  5402. begin
  5403. if Trim(Copy(GetDisplayText(i),1,indlen))='' then
  5404. S:=''
  5405. else
  5406. S:=GetDisplayText(i);
  5407. dec(i);
  5408. end;
  5409. if (S='') then
  5410. Indlen:=1
  5411. else
  5412. begin
  5413. i:=1;
  5414. while (i<=Length(S)) and (S[i]=' ') do
  5415. inc(i);
  5416. indlen:=indlen-i+1;
  5417. if indlen<=0 then
  5418. indlen:=1;
  5419. end;
  5420. end
  5421. else
  5422. Indlen:=1;}
  5423. Indlen:=GetIndentSize;
  5424. {selection Start and End move along}
  5425. if SelStart.X>0 then dec(SelStart.X,Indlen);
  5426. if SelStart.X<0 then SelStart.X:=0;
  5427. if SelEnd.X>0 then dec(SelEnd.X,Indlen);
  5428. if SelEnd.X<0 then begin SelEnd.X:=0; inc(SelEnd.Y); end;
  5429. {do indent line by line}
  5430. for i:=selstart.y to ey do
  5431. begin
  5432. S:=GetLineText(i);
  5433. k:=0;
  5434. for j:=1 to indlen do
  5435. if (length(s)>1) and (S[1]=' ') then
  5436. begin
  5437. Delete(s,1,1);
  5438. inc(k);
  5439. end;
  5440. SetLineText(i,S);
  5441. if k>0 then
  5442. begin
  5443. Pos.Y:=i;
  5444. Pos.X:=0;
  5445. AddAction(eaDeleteText,Pos,Pos,CharStr(' ',k),GetFlags);
  5446. end;
  5447. end;
  5448. SetCurPtr(CurPos.X,CurPos.Y);
  5449. {after SetCurPtr return PersistentBlocks as it was before}
  5450. if not WasPersistentBlocks then
  5451. SetFlags(GetFlags and (not longword(efPersistentBlocks)));
  5452. UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
  5453. DrawLines(CurPos.Y);
  5454. SetModified(true);
  5455. CloseGroupedAction(eaUnindentBlock);
  5456. UnLock;
  5457. end;
  5458. procedure TCustomCodeEditor.SelectWord;
  5459. const WordChars = ['A'..'Z','a'..'z','0'..'9','_'];
  5460. var S : String;
  5461. StartPos,EndPos : byte;
  5462. A,B: TPoint;
  5463. begin
  5464. A:=CurPos;
  5465. B:=CurPos;
  5466. S:=GetDisplayText(A.Y);
  5467. StartPos:=A.X+1;
  5468. EndPos:=StartPos;
  5469. if not (S[StartPos] in WordChars) then
  5470. exit
  5471. else
  5472. begin
  5473. While (StartPos>1) and (S[StartPos-1] in WordChars) do
  5474. Dec(StartPos);
  5475. While (EndPos<Length(S)) and (S[EndPos+1] in WordChars) do
  5476. Inc(EndPos);
  5477. A.X:=StartPos-1;
  5478. B.X:=EndPos;
  5479. SetSelection(A,B);
  5480. end;
  5481. end;
  5482. procedure TCustomCodeEditor.SelectLine;
  5483. var A,B: TPoint;
  5484. begin
  5485. if CurPos.Y<GetLineCount then
  5486. begin
  5487. A.Y:=CurPos.Y; A.X:=0;
  5488. B.Y:=CurPos.Y+1; B.X:=0;
  5489. SetSelection(A,B);
  5490. end;
  5491. end;
  5492. procedure TCustomCodeEditor.WriteBlock;
  5493. var FileName: string;
  5494. S: PBufStream;
  5495. begin
  5496. if ValidBlock=false then Exit;
  5497. FileName:='';
  5498. if EditorDialog(edWriteBlock, @FileName) <> cmCancel then
  5499. begin
  5500. FileName := FExpand(FileName);
  5501. New(S, Init(FileName, stCreate, 4096));
  5502. if (S=nil) or (S^.Status<>stOK) then
  5503. EditorDialog(edCreateError,@FileName)
  5504. else
  5505. if SaveAreaToStream(S,SelStart,SelEnd)=false then
  5506. EditorDialog(edWriteError,@FileName);
  5507. if Assigned(S) then Dispose(S, Done);
  5508. end;
  5509. end;
  5510. procedure TCustomCodeEditor.ReadBlock;
  5511. var FileName: string;
  5512. S: PFastBufStream;
  5513. E: PCodeEditor;
  5514. R: TRect;
  5515. begin
  5516. if IsReadOnly then Exit;
  5517. FileName:='';
  5518. if EditorDialog(edReadBlock, @FileName) <> cmCancel then
  5519. begin
  5520. FileName := FExpand(FileName);
  5521. New(S, Init(FileName, stOpenRead, 4096));
  5522. if (S=nil) or (S^.Status<>stOK) then
  5523. EditorDialog(edReadError,@FileName)
  5524. else
  5525. begin
  5526. R.Assign(0,0,0,0);
  5527. New(E, Init(R,nil,nil,nil,nil));
  5528. AddGroupedAction(eaReadBlock);
  5529. if E^.LoadFromStream(S)=false then
  5530. EditorDialog(edReadError,@FileName)
  5531. else
  5532. begin
  5533. E^.SelectAll(true);
  5534. Self.InsertFrom(E);
  5535. end;
  5536. CloseGroupedAction(eaReadBlock);
  5537. Dispose(E, Done);
  5538. end;
  5539. if Assigned(S) then Dispose(S, Done);
  5540. end;
  5541. end;
  5542. procedure TCustomCodeEditor.PrintBlock;
  5543. begin
  5544. NotImplemented; Exit;
  5545. end;
  5546. function TCustomCodeEditor.SelectCodeTemplate(var ShortCut: string): boolean;
  5547. begin
  5548. { Abstract }
  5549. SelectCodeTemplate:=false;
  5550. end;
  5551. procedure TCustomCodeEditor.ExpandCodeTemplate;
  5552. var Line : sw_astring;
  5553. ShortCutInEditor,ShortCut: string;
  5554. X,Y,I,LineIndent: sw_integer;
  5555. CodeLines: PUnsortedStringCollection;
  5556. CanJump: boolean;
  5557. CP: TPoint;
  5558. begin
  5559. {
  5560. The usage of editing primitives in this routine make it pretty slow, but
  5561. its speed is still acceptable and they make the implementation of Undo
  5562. much easier... - Gabor
  5563. }
  5564. if IsReadOnly then Exit;
  5565. Lock;
  5566. CP.X:=-1; CP.Y:=-1;
  5567. Line:=GetDisplayText(CurPos.Y);
  5568. X:=CurPos.X; ShortCut:='';
  5569. if X<=length(Line) then
  5570. while (X>0) and (Line[X] in (NumberChars+AlphaChars)) do
  5571. begin
  5572. ShortCut:=Line[X]+ShortCut;
  5573. Dec(X);
  5574. end;
  5575. ShortCutInEditor:=ShortCut;
  5576. New(CodeLines, Init(10,10));
  5577. if (ShortCut='') or (not TranslateCodeTemplate(ShortCut,CodeLines)) then
  5578. if SelectCodeTemplate(ShortCut) then
  5579. TranslateCodeTemplate(ShortCut,CodeLines);
  5580. if CodeLines^.Count>0 then
  5581. begin
  5582. LineIndent:=X;
  5583. SetCurPtr(X,CurPos.Y);
  5584. if Copy(ShortCut,1,length(ShortCutInEditor))=ShortCutInEditor then
  5585. begin
  5586. for I:=1 to length(ShortCutInEditor) do
  5587. DelChar;
  5588. end
  5589. else
  5590. { restore correct position }
  5591. SetCurPtr(X+Length(ShortCutInEditor),CurPos.Y);
  5592. for Y:=0 to CodeLines^.Count-1 do
  5593. begin
  5594. Line:=GetStr(CodeLines^.At(Y));
  5595. CanJump:=false;
  5596. if (Y>0) then
  5597. begin
  5598. CanJump:=Trim(GetLineText(CurPos.Y))='';
  5599. if CanJump=false then
  5600. begin
  5601. (* for X:=1 to LineIndent do { indent template lines to align }
  5602. AddChar(' '); { them to the first line }*)
  5603. InsertText(CharStr(' ',LineIndent));
  5604. end
  5605. else
  5606. SetCurPtr(CurPos.X+LineIndent,CurPos.Y);
  5607. end;
  5608. I:=Pos(CodeTemplateCursorChar,Line);
  5609. if I>0 then
  5610. begin
  5611. Delete(Line,I,1);
  5612. CP.X:=CurPos.X+I-1;
  5613. CP.Y:=CurPos.Y;
  5614. end;
  5615. InsertText(Line);
  5616. if Y<CodeLines^.Count-1 then
  5617. begin
  5618. InsertNewLine; { line break }
  5619. if CanJump=false then
  5620. begin
  5621. while CurPos.X>0 do { unindent }
  5622. begin
  5623. SetCurPtr(CurPos.X-1,CurPos.Y);
  5624. DelChar;
  5625. end;
  5626. end
  5627. else
  5628. SetCurPtr(0,CurPos.Y);
  5629. end;
  5630. end;
  5631. end;
  5632. Dispose(CodeLines, Done);
  5633. if (CP.X<>-1) and (CP.Y<>-1) then
  5634. SetCurPtr(CP.X,CP.Y);
  5635. UnLock;
  5636. end;
  5637. procedure TCustomCodeEditor.AddChar(C: AnsiChar);
  5638. const OpenBrackets : string[10] = '[({';
  5639. CloseBrackets : string[10] = '])}';
  5640. var S,SC,TabS: sw_astring;
  5641. BI: byte;
  5642. CI,TabStart,LocTabSize : Sw_integer;
  5643. SP: TPoint;
  5644. HoldUndo : boolean;
  5645. begin
  5646. if IsReadOnly then Exit;
  5647. Lock;
  5648. if not (Clipboard=@Self) and IsFlagSet(efOverwriteBlocks) and InSelectionArea then
  5649. DelSelect; {delete selection before}
  5650. SP:=CurPos;
  5651. HoldUndo:=GetStoreUndo;
  5652. SetStoreUndo(false);
  5653. if (C<>TAB) or IsFlagSet(efUseTabCharacters) then
  5654. SC:=C
  5655. else
  5656. begin
  5657. LocTabSize:=GetTabSize - (CurPos.X mod GetTabSize);
  5658. if (CurPos.Y<=1) or not IsFlagSet(efAutoIndent) then
  5659. SC:=CharStr(' ',LocTabSize)
  5660. else
  5661. begin
  5662. S:=GetLineText(CurPos.Y-1);
  5663. BI:=CurPos.X+1;
  5664. while (BI<=Length(S)) and (S[BI]=' ') do
  5665. inc(BI);
  5666. if (BI=CurPos.X+1) or (BI>Length(S)) then
  5667. SC:=CharStr(' ',LocTabSize)
  5668. else
  5669. SC:=CharStr(' ',BI-CurPos.X-1);
  5670. end;
  5671. end;
  5672. S:=GetLineText(CurPos.Y);
  5673. if CharIdxToLinePos(CurPos.Y,length(S))<CurPos.X then
  5674. begin
  5675. S:=S+CharStr(' ',CurPos.X-CharIdxToLinePos(CurPos.Y,length(S)){-1});
  5676. SetLineText(CurPos.Y,S);
  5677. end;
  5678. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  5679. {$if sizeof(sw_astring)>8 only if ShortString}
  5680. if CI>High(S) then
  5681. begin
  5682. Unlock;
  5683. exit;
  5684. end;
  5685. {$endif}
  5686. SP.X:=CharIdxToLinePos(CurPos.Y,CI); {actual changes are going to be here (tab space adjustment)}
  5687. if (CI>0) and (S[CI]=TAB) and not IsFlagSet(efUseTabCharacters) then
  5688. begin
  5689. if CI=1 then
  5690. TabStart:=0
  5691. else
  5692. TabStart:=CharIdxToLinePos(CurPos.Y,CI-1)+1;
  5693. if SC=Tab then TabS:=Tab else
  5694. TabS:=CharStr(' ',CurPos.X-TabStart);
  5695. SetLineText(CurPos.Y,copy(S,1,CI-1)+TabS+SC+copy(S,CI+1,Length(S)));
  5696. SetCurPtr(CharIdxToLinePos(CurPos.Y,CI+length(TabS)+length(SC)),CurPos.Y);
  5697. end
  5698. else
  5699. begin
  5700. if Overwrite and (CI<=length(S)) then
  5701. begin
  5702. SetLineText(CurPos.Y,copy(S,1,CI-1)+SC+copy(S,CI+length(SC),Length(S)));
  5703. end
  5704. else
  5705. SetLineText(CurPos.Y,copy(S,1,CI-1)+SC+copy(S,CI,Length(S)));
  5706. SetCurPtr(CharIdxToLinePos(CurPos.Y,CI+length(SC)),CurPos.Y);
  5707. end;
  5708. { must be before CloseBrackets !! }
  5709. SetStoreUndo(HoldUndo);
  5710. if Overwrite then
  5711. Addaction(eaOverwriteText,SP,CurPos,Copy(S,CI,length(SC)),GetFlags)
  5712. else
  5713. Addaction(eaInsertText,SP,CurPos,SC,GetFlags);
  5714. SetStoreUndo(false);
  5715. if IsFlagSet(efAutoBrackets) then
  5716. begin
  5717. BI:=Pos(C,OpenBrackets);
  5718. if (BI>0) then
  5719. begin
  5720. SetStoreUndo(HoldUndo);
  5721. AddChar(CloseBrackets[BI]);
  5722. SetStoreUndo(false);
  5723. SetCurPtr(CurPos.X-1,CurPos.Y);
  5724. end;
  5725. end;
  5726. UpdateAttrs(CurPos.Y,attrAll);
  5727. if GetInsertMode then
  5728. AdjustSelection(CurPos.X-SP.X,CurPos.Y-SP.Y);
  5729. DrawLines(CurPos.Y);
  5730. SetStoreUndo(HoldUndo);
  5731. SetModified(true);
  5732. UnLock;
  5733. end;
  5734. const
  5735. linelimit = 200;
  5736. procedure TCustomCodeEditor.PasteText(P:PAnsiChar; ASize:sw_integer);
  5737. var
  5738. StorePos : TPoint;
  5739. first : boolean;
  5740. IsNewLine: boolean;
  5741. procedure InsertStringWrap(const s: sw_astring; var i : Longint);
  5742. var
  5743. BPos,EPos: TPoint;
  5744. begin
  5745. if first then
  5746. begin
  5747. { we need to cut the line in two
  5748. if not at end of line PM }
  5749. if IsNewLine then
  5750. InsertNewLine;
  5751. SetCurPtr(StorePos.X,StorePos.Y);
  5752. InsertText(s);
  5753. first:=false;
  5754. end
  5755. else
  5756. begin
  5757. Inc(i);
  5758. if IsNewLine then
  5759. begin
  5760. InsertLine(i,s);
  5761. BPos.X:=0;BPos.Y:=i;
  5762. EPOS.X:=Length(s);EPos.Y:=i;
  5763. AddAction(eaInsertLine,BPos,EPos,GetDisplayText(i),GetFlags);
  5764. end else
  5765. begin
  5766. SetCurPtr(0,i);
  5767. InsertText(s);
  5768. end;
  5769. end;
  5770. end;
  5771. var
  5772. l,i,len,len10 : longint;
  5773. p10,p2,p13 : PAnsiChar;
  5774. s : sw_astring;
  5775. begin
  5776. Lock;
  5777. first:=true;
  5778. StorePos:=CurPos;
  5779. i:=CurPos.Y;
  5780. if ASize>500 then
  5781. PushInfo(msg_readingwinclipboard);
  5782. AddGroupedAction(eaPasteWin);
  5783. if not (Clipboard=@Self) and IsFlagSet(efOverwriteBlocks) and InSelectionArea then
  5784. DelSelect; {delete selection before paste}
  5785. p2:=p;
  5786. len:=strlen(p2);
  5787. // issue lines ((#13)#10 terminated) of maximally "linelimit" chars.
  5788. // does not take initial X position into account
  5789. repeat
  5790. p13:=strpos(p2,#13);
  5791. p10:=strpos(p2,#10);
  5792. {$if sizeof(sw_astring)>8 only if ShortString lines}
  5793. if len> linelimit then
  5794. len:=linelimit;
  5795. {$endif}
  5796. if not assigned(p10) and assigned(p13) then
  5797. p10:=p13;
  5798. IsNewLine:=false;
  5799. if assigned(p10) then
  5800. begin
  5801. IsNewLine:=true;
  5802. len10:=p10-p2;
  5803. if len10<len then
  5804. begin
  5805. if p13+1=p10 then
  5806. dec(len10);
  5807. len:=len10;
  5808. end
  5809. else
  5810. p10:=nil; // signal no cleanup
  5811. end;
  5812. setlength(s,len);
  5813. if len>0 then
  5814. move(p2^,s[1],len);
  5815. // cleanup
  5816. if assigned(p10) then
  5817. p2:=p10+1
  5818. else
  5819. inc(p2,len);
  5820. insertstringwrap(s,i);
  5821. len:=strlen(p2);
  5822. until len=0;
  5823. SetCurPtr(StorePos.X,StorePos.Y); // y+i to get after paste?
  5824. SetModified(true);
  5825. UpdateAttrs(StorePos.Y,attrAll);
  5826. CloseGroupedAction(eaPasteWin);
  5827. Update;
  5828. if ASize>500 then
  5829. PopInfo;
  5830. DrawView;
  5831. UnLock;
  5832. end;
  5833. {$ifdef WinClipSupported}
  5834. function TCustomCodeEditor.ClipPasteWin: Boolean;
  5835. var
  5836. OK: boolean;
  5837. l : longint;
  5838. p : PAnsiChar;
  5839. begin
  5840. Lock;
  5841. OK:=WinClipboardSupported;
  5842. if OK then
  5843. begin
  5844. l:=GetTextWinClipboardSize;
  5845. if l=0 then
  5846. OK:=false
  5847. else
  5848. OK:=GetTextWinClipBoardData(p,l);
  5849. if OK then
  5850. begin
  5851. PasteText(p,l);
  5852. { we must free the allocated memory }
  5853. freemem(p,l);
  5854. end;
  5855. end;
  5856. ClipPasteWin:=OK;
  5857. UnLock;
  5858. end;
  5859. function TCustomCodeEditor.ClipCopyWin: Boolean;
  5860. var OK,ShowInfo: boolean;
  5861. p,p2 : PAnsiChar;
  5862. s : sw_astring;
  5863. i,str_begin,str_end,NumLines,PcLength : longint;
  5864. begin
  5865. NumLines:=SelEnd.Y-SelStart.Y;
  5866. if (NumLines>0) or (SelEnd.X>SelStart.X) then
  5867. Inc(NumLines);
  5868. if NumLines=0 then
  5869. exit;
  5870. Lock;
  5871. ShowInfo:=SelEnd.Y-SelStart.Y>50;
  5872. if ShowInfo then
  5873. PushInfo(msg_copyingwinclipboard);
  5874. { First calculate needed size }
  5875. { for newlines first + 1 for terminal #0 }
  5876. PcLength:=Length(EOL)*(NumLines-1)+1;
  5877. { overestimated but can not be that big PM }
  5878. for i:=SelStart.Y to SelEnd.Y do
  5879. PCLength:=PCLength+Length(GetLineText(i));
  5880. getmem(p,PCLength);
  5881. i:=SelStart.Y;
  5882. s:=GetLineText(i);
  5883. str_begin:=LinePosToCharIdx(i,SelStart.X);
  5884. if SelEnd.Y>SelStart.Y then
  5885. str_end:=Length(S)
  5886. else
  5887. str_end:=LinePosToCharIdx(i,SelEnd.X)-1;
  5888. s:=copy(s,str_begin,str_end-str_begin+1);
  5889. {$if sizeof(sw_astring)>8}
  5890. strpcopy(p,s);
  5891. {$else}
  5892. s:=s+#0;
  5893. Move(S[1],P^,Length(S));
  5894. {$endif}
  5895. p2:=strend(p);
  5896. inc(i);
  5897. while i<SelEnd.Y do
  5898. begin
  5899. s:=EOL+GetLineText(i);
  5900. {$if sizeof(sw_astring)>8}
  5901. strpcopy(p2,s);
  5902. {$else}
  5903. s:=s+#0;
  5904. Move(S[1],P2^,Length(S));
  5905. {$endif}
  5906. p2:=strend(p2);
  5907. Inc(i);
  5908. end;
  5909. if SelEnd.Y>SelStart.Y then
  5910. begin
  5911. s:=copy(GetLineText(i),1,LinePosToCharIdx(i,SelEnd.X)-1);
  5912. {$if sizeof(sw_astring)>8}
  5913. strpcopy(p2,EOL+s);
  5914. {$else}
  5915. s:=EOL+s+#0;
  5916. Move(S[1],P2^,Length(S));
  5917. {$endif}
  5918. end;
  5919. OK:=WinClipboardSupported;
  5920. if OK then
  5921. begin
  5922. OK:=SetTextWinClipBoardData(p,strlen(p));
  5923. end;
  5924. ClipCopyWin:=OK;
  5925. if ShowInfo then
  5926. PopInfo;
  5927. Freemem(p,PCLength);
  5928. UnLock;
  5929. end;
  5930. {$endif WinClipSupported}
  5931. function TCustomCodeEditor.ClipCopy: Boolean;
  5932. var ShowInfo,CanPaste: boolean;
  5933. begin
  5934. Lock;
  5935. {AddGroupedAction(eaCopy);
  5936. can we undo a copy ??
  5937. maybe as an Undo Paste in Clipboard !! }
  5938. clipcopy:=false;
  5939. showinfo:=false;
  5940. if (clipboard<>nil) and (clipboard<>@self) then
  5941. begin
  5942. ShowInfo:=SelEnd.Y-SelStart.Y>50;
  5943. if ShowInfo then
  5944. PushInfo(msg_copyingclipboard);
  5945. clipcopy:=Clipboard^.InsertFrom(@Self);
  5946. if ShowInfo then
  5947. PopInfo;
  5948. {Enable paste command.}
  5949. CanPaste:=((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
  5950. (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
  5951. SetCmdState(FromClipCmds,CanPaste);
  5952. end;
  5953. UnLock;
  5954. end;
  5955. procedure TCustomCodeEditor.ClipCut;
  5956. var
  5957. ShowInfo,CanPaste : boolean;
  5958. begin
  5959. if IsReadOnly then Exit;
  5960. Lock;
  5961. AddGroupedAction(eaCut);
  5962. DontConsiderShiftState:=true;
  5963. if (clipboard<>nil) and (clipboard<>@self) then
  5964. begin
  5965. ShowInfo:=SelEnd.Y-SelStart.Y>50;
  5966. if ShowInfo then
  5967. PushInfo(msg_cutting);
  5968. if Clipboard^.InsertFrom(@Self) then
  5969. begin
  5970. if not IsClipBoard then
  5971. DelSelect;
  5972. SetModified(true);
  5973. end;
  5974. if ShowInfo then
  5975. PopInfo;
  5976. CanPaste:=((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
  5977. (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
  5978. SetCmdState(FromClipCmds,CanPaste);
  5979. end;
  5980. CloseGroupedAction(eaCut);
  5981. UnLock;
  5982. DontConsiderShiftState:=false;
  5983. end;
  5984. procedure TCustomCodeEditor.ClipPaste;
  5985. var
  5986. ShowInfo : boolean;
  5987. begin
  5988. if IsReadOnly then Exit;
  5989. DontConsiderShiftState:=true;
  5990. Lock;
  5991. AddGroupedAction(eaPaste);
  5992. if Clipboard<>nil then
  5993. begin
  5994. ShowInfo:=Clipboard^.SelEnd.Y-Clipboard^.SelStart.Y>50;
  5995. if ShowInfo then
  5996. PushInfo(msg_pastingclipboard);
  5997. InsertFrom(Clipboard);
  5998. if ShowInfo then
  5999. PopInfo;
  6000. end;
  6001. CloseGroupedAction(eaPaste);
  6002. UnLock;
  6003. DontConsiderShiftState:=false;
  6004. end;
  6005. procedure TCustomCodeEditor.Undo;
  6006. begin
  6007. NotImplemented; Exit;
  6008. end;
  6009. procedure TCustomCodeEditor.Redo;
  6010. begin
  6011. NotImplemented; Exit;
  6012. end;
  6013. procedure TCustomCodeEditor.GotoLine;
  6014. const
  6015. GotoRec: TGotoLineDialogRec = (LineNo:'1';Lines:0); {keep previous goto line number}
  6016. begin
  6017. with GotoRec do
  6018. begin
  6019. Lines:=GetLineCount;
  6020. {Linecount can be 0, but in that case there still is a cursor blinking in top
  6021. of the window, which will become line 1 as soon as sometype hits a key.}
  6022. if lines=0 then
  6023. lines:=1;
  6024. if EditorDialog(edGotoLine, @GotoRec) <> cmCancel then
  6025. begin
  6026. Lock;
  6027. SetCurPtr(0,StrToInt(LineNo)-1);
  6028. TrackCursor(do_centre);
  6029. UnLock;
  6030. end;
  6031. end;
  6032. end;
  6033. procedure TCustomCodeEditor.Find;
  6034. var
  6035. FindRec: TFindDialogRec;
  6036. DoConf: boolean;
  6037. CurrentWord : string;
  6038. begin
  6039. with FindRec do
  6040. begin
  6041. Find := FindStr;
  6042. CurrentWord:=GetCurrentWord;
  6043. if CurrentWord<>'' then
  6044. Find:=CurrentWord;
  6045. {$ifdef TEST_REGEXP}
  6046. Options := ((FindFlags and ffmOptionsFind) shr ffsOptions) or
  6047. ((FindFlags and ffUseRegExp) shr ffsUseRegExpFind);
  6048. {$else not TEST_REGEXP}
  6049. Options := (FindFlags and ffmOptions) shr ffsOptions;
  6050. {$endif TEST_REGEXP}
  6051. Direction := (FindFlags and ffmDirection) shr ffsDirection;
  6052. Scope := (FindFlags and ffmScope) shr ffsScope;
  6053. Origin := (FindFlags and ffmOrigin) shr ffsOrigin;
  6054. DoConf:= (FindFlags and ffPromptOnReplace)<>0;
  6055. FindReplaceEditor:=@self;
  6056. if EditorDialog(edFind, @FindRec) <> cmCancel then
  6057. begin
  6058. FindStr := Find;
  6059. {$ifdef TEST_REGEXP}
  6060. FindFlags := ((Options and ffmOptionsFind) shl ffsOptions) or (Direction shl ffsDirection) or
  6061. ((Options and ffmUseRegExpFind) shl ffsUseRegExpFind) or
  6062. (Scope shl ffsScope) or (Origin shl ffsOrigin);
  6063. {$else : not TEST_REGEXP}
  6064. FindFlags := ((Options and ffmOptions) shl ffsOptions) or (Direction shl ffsDirection) or
  6065. (Scope shl ffsScope) or (Origin shl ffsOrigin);
  6066. {$endif TEST_REGEXP}
  6067. FindFlags := FindFlags and not ffDoReplace;
  6068. if DoConf then
  6069. FindFlags := (FindFlags or ffPromptOnReplace);
  6070. SearchRunCount:=0;
  6071. if FindStr<>'' then
  6072. DoSearchReplace
  6073. else
  6074. EditorDialog(edSearchFailed,nil);
  6075. end;
  6076. FindReplaceEditor:=nil;
  6077. end;
  6078. end;
  6079. procedure TCustomCodeEditor.Replace;
  6080. var
  6081. ReplaceRec: TReplaceDialogRec;
  6082. Re: word;
  6083. begin
  6084. if IsReadOnly then Exit;
  6085. with ReplaceRec do
  6086. begin
  6087. Find := FindStr;
  6088. if GetCurrentWord<>'' then
  6089. Find:=GetCurrentWord;
  6090. Replace := ReplaceStr;
  6091. {$ifdef TEST_REGEXP}
  6092. Options := (FindFlags and ffmOptions) shr ffsOptions or
  6093. (FindFlags and ffUseRegExp) shr ffsUseRegExpReplace;
  6094. {$else not TEST_REGEXP}
  6095. Options := (FindFlags and ffmOptions) shr ffsOptions;
  6096. {$endif TEST_REGEXP}
  6097. Direction := (FindFlags and ffmDirection) shr ffsDirection;
  6098. Scope := (FindFlags and ffmScope) shr ffsScope;
  6099. Origin := (FindFlags and ffmOrigin) shr ffsOrigin;
  6100. FindReplaceEditor:=@self;
  6101. Re:=EditorDialog(edReplace, @ReplaceRec);
  6102. FindReplaceEditor:=nil;
  6103. if Re <> cmCancel then
  6104. begin
  6105. FindStr := Find;
  6106. ReplaceStr := Replace;
  6107. FindFlags := (Options shl ffsOptions) or (Direction shl ffsDirection) or
  6108. {$ifdef TEST_REGEXP}
  6109. ((Options and ffmUseRegExpReplace) shl ffsUseRegExpReplace) or
  6110. {$endif TEST_REGEXP}
  6111. (Scope shl ffsScope) or (Origin shl ffsOrigin);
  6112. FindFlags := FindFlags or ffDoReplace;
  6113. if Re = cmYes then
  6114. FindFlags := FindFlags or ffReplaceAll;
  6115. SearchRunCount:=0;
  6116. if FindStr<>'' then
  6117. DoSearchReplace
  6118. else
  6119. EditorDialog(edSearchFailed,nil);
  6120. end;
  6121. end;
  6122. end;
  6123. procedure TCustomCodeEditor.DoSearchReplace;
  6124. var S: sw_astring;
  6125. DX,DY,P,Y,X: sw_integer;
  6126. Count: sw_integer;
  6127. Found,CanExit: boolean;
  6128. SForward,DoReplace,DoReplaceAll: boolean;
  6129. {$ifdef TEST_REGEXP}
  6130. UseRegExp : boolean;
  6131. RegExpEngine : TRegExprEngine;
  6132. RegExpFlags : tregexprflags;
  6133. regexpindex,regexplen : longint;
  6134. findstrpchar : PAnsiChar;
  6135. {$endif TEST_REGEXP}
  6136. LeftOK,RightOK: boolean;
  6137. FoundCount: sw_integer;
  6138. A,B: TPoint;
  6139. AreaStart,AreaEnd: TPoint;
  6140. CanReplace,Confirm: boolean;
  6141. Re: word;
  6142. IFindStr : string;
  6143. BT : BTable;
  6144. Overwriting : boolean;
  6145. function ContainsText(const SubS:string;var S: sw_astring; Start: Sw_integer): Sw_integer;
  6146. var
  6147. P: Sw_Integer;
  6148. begin
  6149. if Start<=0 then
  6150. P:=0
  6151. else
  6152. begin
  6153. if SForward then
  6154. begin
  6155. if Start>length(s) then
  6156. P:=0
  6157. else if FindFlags and ffCaseSensitive<>0 then
  6158. P:=BMFScan(S[Start],length(s)+1-Start,FindStr,Bt)+1
  6159. else
  6160. P:=BMFIScan(S[Start],length(s)+1-Start,IFindStr,Bt)+1;
  6161. if P>0 then
  6162. Inc(P,Start-1);
  6163. end
  6164. else
  6165. begin
  6166. if start>length(s) then
  6167. start:=length(s);
  6168. if FindFlags and ffCaseSensitive<>0 then
  6169. P:=BMBScan(S[1],Start,FindStr,Bt)+1
  6170. else
  6171. P:=BMBIScan(S[1],Start,IFindStr,Bt)+1;
  6172. end;
  6173. end;
  6174. ContainsText:=P;
  6175. end;
  6176. function InArea(X,Y: sw_integer): boolean;
  6177. begin
  6178. InArea:=((AreaStart.Y=Y) and (AreaStart.X<=X)) or
  6179. ((AreaStart.Y<Y) and (Y<AreaEnd.Y)) or
  6180. ((AreaEnd.Y=Y) and (X<=AreaEnd.X));
  6181. end;
  6182. var CurDY: sw_integer;
  6183. begin
  6184. if FindStr='' then
  6185. begin
  6186. Find;
  6187. { Find will call DoFindReplace at end again
  6188. so we need to exit directly now PM }
  6189. exit;
  6190. end;
  6191. Inc(SearchRunCount);
  6192. SForward:=(FindFlags and ffmDirection)=ffForward;
  6193. DoReplace:=(FindFlags and ffDoReplace)<>0;
  6194. Confirm:=(FindFlags and ffPromptOnReplace)<>0;
  6195. DoReplaceAll:=(FindFlags and ffReplaceAll)<>0;
  6196. {$ifdef TEST_REGEXP}
  6197. UseRegExp:=(FindFlags and ffUseRegExp)<>0;
  6198. if UseRegExp then
  6199. begin
  6200. if FindFlags and ffCaseSensitive<>0 then
  6201. RegExpFlags:=[ref_caseinsensitive]
  6202. else
  6203. RegExpFlags:=[];
  6204. getmem(findstrpchar,length(findstr)+1);
  6205. strpcopy(findstrpchar,findstr);
  6206. RegExpEngine:=GenerateRegExprEngine(findstrpchar,RegExpFlags);
  6207. strdispose(findstrpchar);
  6208. end;
  6209. {$endif TEST_REGEXP}
  6210. Count:=GetLineCount;
  6211. FoundCount:=0;
  6212. { Empty file ? }
  6213. if Count=0 then
  6214. begin
  6215. EditorDialog(edSearchFailed,nil);
  6216. exit;
  6217. end;
  6218. if SForward then
  6219. DY:=1
  6220. else
  6221. DY:=-1;
  6222. DX:=DY;
  6223. if FindStr<>'' then
  6224. PushInfo('Looking for "'+FindStr+'"');
  6225. if (FindFlags and ffmScope)=ffGlobal then
  6226. begin
  6227. AreaStart.X:=0;
  6228. AreaStart.Y:=0;
  6229. AreaEnd.X:=length(GetDisplayText(Count-1));
  6230. AreaEnd.Y:=Count-1;
  6231. end
  6232. else
  6233. begin
  6234. AreaStart:=SelStart;
  6235. AreaEnd:=SelEnd;
  6236. end;
  6237. { set a y value being inside the areal }
  6238. Y:=Min(CurPos.Y,Count-1);
  6239. if sForward then
  6240. X:=CurPos.X-1
  6241. else
  6242. { if you change this, pleas check that repeated backward searching for single chars still works
  6243. and that data is still found if searching starts outside the current line }
  6244. X:=Min(CurPos.X,length(GetDisplayText(Y)));
  6245. if SearchRunCount=1 then
  6246. if (FindFlags and ffmOrigin)=ffEntireScope then
  6247. if SForward then
  6248. begin
  6249. X:=AreaStart.X-1;
  6250. Y:=AreaStart.Y;
  6251. end
  6252. else
  6253. begin
  6254. X:=AreaEnd.X+1;
  6255. Y:=AreaEnd.Y;
  6256. end;
  6257. if FindFlags and ffCaseSensitive<>0 then
  6258. begin
  6259. if SForward then
  6260. BMFMakeTable(FindStr,bt)
  6261. else
  6262. BMBMakeTable(FindStr,bt);
  6263. end
  6264. else
  6265. begin
  6266. IFindStr:=upcase(FindStr);
  6267. if SForward then
  6268. BMFMakeTable(IFindStr,bt)
  6269. else
  6270. BMBMakeTable(IFindStr,bt);
  6271. end;
  6272. inc(X,DX);
  6273. CanExit:=false;
  6274. if not DoReplace or (not Confirm and (Owner<>nil)) then
  6275. Owner^.Lock;
  6276. if InArea(X,Y) then
  6277. repeat
  6278. CurDY:=DY;
  6279. S:=GetDisplayText(Y);
  6280. if X>length(S)-1 then
  6281. X:=length(S)-1;
  6282. {$ifdef TEST_REGEXP}
  6283. if UseRegExp then
  6284. begin
  6285. getmem(findstrpchar,length(Copy(S,X+1,Length(S)))+1);
  6286. strpcopy(findstrpchar,Copy(S,X+1,Length(S)));
  6287. { If start of line is required do check other positions PM }
  6288. if (FindStr[1]='^') and (X<>0) then
  6289. Found:=false
  6290. else
  6291. Found:=RegExprPos(RegExpEngine,findstrpchar,regexpindex,regexplen);
  6292. strdispose(findstrpchar);
  6293. P:=regexpindex+X+1;
  6294. end
  6295. else
  6296. {$endif TEST_REGEXP}
  6297. begin
  6298. P:=ContainsText(FindStr,S,X+1);
  6299. Found:=P<>0;
  6300. end;
  6301. if Found then
  6302. begin
  6303. A.X:=P-1;
  6304. A.Y:=Y;
  6305. B.Y:=Y;
  6306. {$ifdef TEST_REGEXP}
  6307. if UseRegExp then
  6308. B.X:=A.X+regexplen
  6309. else
  6310. {$endif TEST_REGEXP}
  6311. B.X:=A.X+length(FindStr);
  6312. end;
  6313. Found:=Found and InArea(A.X,A.Y);
  6314. if Found and ((FindFlags and ffWholeWordsOnly)<>0) then
  6315. begin
  6316. LeftOK:=(A.X<=0) or (not( (S[A.X] in AlphaChars+NumberChars) ));
  6317. RightOK:=(B.X>=length(S)) or (not( (S[B.X+1] in AlphaChars+NumberChars) ));
  6318. Found:=LeftOK and RightOK;
  6319. if not Found then
  6320. begin
  6321. CurDY:=0;
  6322. If SForward then
  6323. begin
  6324. X:=B.X+1;
  6325. if X>length(S) then
  6326. CurDY:=DY;
  6327. end
  6328. else
  6329. begin
  6330. X:=A.X-1;
  6331. if X<0 then
  6332. CurDY:=DY;
  6333. end;
  6334. end;
  6335. end;
  6336. if Found then
  6337. begin
  6338. Inc(FoundCount);
  6339. Lock;
  6340. if SForward then
  6341. SetCurPtr(B.X,B.Y)
  6342. else
  6343. SetCurPtr(A.X,A.Y);
  6344. TrackCursor(do_centre);
  6345. SetHighlight(A,B);
  6346. UnLock;
  6347. CurDY:=0;
  6348. if not DoReplace then
  6349. begin
  6350. CanExit:=true;
  6351. If SForward then
  6352. begin
  6353. X:=B.X;
  6354. Y:=B.Y;
  6355. end
  6356. else
  6357. begin
  6358. X:=A.X;
  6359. Y:=A.Y;
  6360. end;
  6361. end
  6362. else
  6363. begin
  6364. if not confirm then
  6365. CanReplace:=true
  6366. else
  6367. begin
  6368. Re:=EditorDialog(edReplacePrompt,@CurPos);
  6369. case Re of
  6370. cmYes :
  6371. CanReplace:=true;
  6372. cmNo :
  6373. CanReplace:=false;
  6374. else {cmCancel}
  6375. begin
  6376. CanReplace:=false;
  6377. CanExit:=true;
  6378. end;
  6379. end;
  6380. end;
  6381. if CanReplace then
  6382. begin
  6383. Lock;
  6384. { don't use SetInsertMode here because it changes the cursor shape }
  6385. overwriting:=(GetFlags and efInsertMode)=0;
  6386. SetFlags(GetFlags or efInsertMode);
  6387. SetSelection(A,B);
  6388. DelSelect;
  6389. InsertText(ReplaceStr);
  6390. if SForward then
  6391. begin
  6392. X:=CurPos.X;
  6393. Y:=CurPos.Y;
  6394. end
  6395. else
  6396. begin
  6397. X:=A.X;
  6398. Y:=A.Y;
  6399. end;
  6400. if overwriting then
  6401. SetFlags(GetFlags and (not efInsertMode));
  6402. UnLock;
  6403. end
  6404. else
  6405. begin
  6406. If SForward then
  6407. begin
  6408. X:=B.X;
  6409. Y:=B.Y;
  6410. end
  6411. else
  6412. begin
  6413. X:=A.X;
  6414. Y:=A.Y;
  6415. end;
  6416. end;
  6417. if (DoReplaceAll=false) then
  6418. CanExit:=true;
  6419. end;
  6420. end;
  6421. if (CanExit=false) and (CurDY<>0) then
  6422. begin
  6423. inc(Y,CurDY);
  6424. if SForward then
  6425. X:=0
  6426. else
  6427. X:=254;
  6428. CanExit:=((Y>=Count) and sForward) or (Y<0);
  6429. end;
  6430. if not CanExit then
  6431. CanExit:=(not InArea(X,Y)) and sForward;
  6432. until CanExit;
  6433. if (FoundCount=0) or (DoReplace) then
  6434. SetHighlight(CurPos,CurPos);
  6435. if (DoReplace=false) or ((Confirm=false) and (Owner<>nil)) then
  6436. Owner^.UnLock;
  6437. {if (DoReplace=false) or (Confirm=false) then
  6438. UnLock;}
  6439. if (FoundCount=0) then
  6440. EditorDialog(edSearchFailed,nil);
  6441. if FindStr<>'' then
  6442. PopInfo;
  6443. {$ifdef TEST_REGEXP}
  6444. if UseRegExp then
  6445. DestroyRegExprEngine(RegExpEngine);
  6446. {$endif TEST_REGEXP}
  6447. if (FindFlags and ffmScope)=ffSelectedText then
  6448. { restore selection PM }
  6449. begin
  6450. SetSelection(AreaStart,AreaEnd);
  6451. end;
  6452. end;
  6453. function TCustomCodeEditor.GetAutoBrackets: boolean;
  6454. begin
  6455. GetAutoBrackets:=(GetFlags and efAutoBrackets)<>0;
  6456. end;
  6457. procedure TCustomCodeEditor.SetAutoBrackets(AutoBrackets: boolean);
  6458. begin
  6459. if AutoBrackets then
  6460. SetFlags(GetFlags or efAutoBrackets)
  6461. else
  6462. SetFlags(GetFlags and (not efAutoBrackets));
  6463. end;
  6464. function TCustomCodeEditor.GetInsertMode: boolean;
  6465. begin
  6466. GetInsertMode:=(GetFlags and efInsertMode)<>0;
  6467. end;
  6468. procedure TCustomCodeEditor.SetInsertMode(InsertMode: boolean);
  6469. begin
  6470. if InsertMode then
  6471. SetFlags(GetFlags or efInsertMode)
  6472. else
  6473. SetFlags(GetFlags and (not efInsertMode));
  6474. DrawCursor;
  6475. end;
  6476. { there is a problem with ShiftDel here
  6477. because GetShitState tells to extend the
  6478. selection which gives wrong results (PM) }
  6479. function TCustomCodeEditor.ShouldExtend: boolean;
  6480. var ShiftInEvent: boolean;
  6481. begin
  6482. ShiftInEvent:=false;
  6483. if Assigned(CurEvent) then
  6484. if CurEvent^.What=evKeyDown then
  6485. ShiftInEvent:=((CurEvent^.KeyShift and kbShift)<>0);
  6486. ShouldExtend:=ShiftInEvent and
  6487. not DontConsiderShiftState;
  6488. end;
  6489. procedure TCustomCodeEditor.SetCurPtr(X,Y: sw_integer);
  6490. var OldPos{,OldSEnd,OldSStart}: TPoint;
  6491. Extended: boolean;
  6492. F: PFold;
  6493. begin
  6494. Lock;
  6495. X:=Max(0,Min(MaxLineLength+1,X));
  6496. Y:=Max(0,Min(GetLineCount-1,Y));
  6497. OldPos:=CurPos;
  6498. { OldSEnd:=SelEnd;
  6499. OldSStart:=SelStart;}
  6500. CurPos.X:=X;
  6501. CurPos.Y:=Y;
  6502. TrackCursor(do_not_centre);
  6503. if not IsLineVisible(CurPos.Y) then
  6504. begin
  6505. F:=GetLineFold(CurPos.Y);
  6506. if Assigned(F) then
  6507. F^.Collapse(false);
  6508. end;
  6509. if not NoSelect and ShouldExtend then
  6510. begin
  6511. CheckSels;
  6512. Extended:=false;
  6513. if PointOfs(OldPos)=PointOfs(SelStart) then
  6514. begin
  6515. SetSelection(CurPos,SelEnd);
  6516. Extended:=true;
  6517. end;
  6518. CheckSels;
  6519. if Extended=false then
  6520. if PointOfs(OldPos)=PointOfs(SelEnd) then
  6521. begin
  6522. if not ValidBlock then
  6523. SetSelection(CurPos,CurPos);
  6524. SetSelection(SelStart,CurPos); Extended:=true;
  6525. end;
  6526. CheckSels;
  6527. if not Extended then
  6528. if PointOfs(OldPos)<=PointOfs(CurPos) then
  6529. begin
  6530. SetSelection(OldPos,CurPos);
  6531. Extended:=true;
  6532. end
  6533. else
  6534. begin
  6535. SetSelection(CurPos,OldPos);
  6536. Extended:=true;
  6537. end;
  6538. DrawView;
  6539. end
  6540. else if not IsFlagSet(efPersistentBlocks) then
  6541. begin
  6542. HideSelect;
  6543. DrawView;
  6544. end;
  6545. { if PointOfs(SelStart)=PointOfs(SelEnd) then
  6546. SetSelection(CurPos,CurPos);}
  6547. if (GetFlags and (efHighlightColumn+efHighlightRow))<>0 then
  6548. DrawView;
  6549. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and
  6550. ((Highlight.A.X<>HighLight.B.X) or (Highlight.A.Y<>HighLight.B.Y)) then
  6551. HideHighlight;
  6552. if (OldPos.Y<>CurPos.Y) and (0<=OldPos.Y) and (OldPos.Y<GetLineCount) then
  6553. SetLineText(OldPos.Y,RTrim(GetLineText(OldPos.Y),not IsFlagSet(efUseTabCharacters)));
  6554. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and (GetErrorMessage<>'') then
  6555. SetErrorMessage('');
  6556. { if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and (HighlightRow<>-1) then
  6557. SetHighlightRow(-1);}
  6558. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) then
  6559. AddAction(eaMoveCursor,OldPos,CurPos,'',GetFlags);
  6560. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) then
  6561. PositionChanged;{UpdateIndicator;}
  6562. UnLock;
  6563. end;
  6564. procedure TCustomCodeEditor.CheckSels;
  6565. begin
  6566. if (SelStart.Y>SelEnd.Y) or
  6567. ( (SelStart.Y=SelEnd.Y) and (SelStart.X>SelEnd.X) ) then
  6568. SetSelection(SelEnd,SelStart);
  6569. end;
  6570. procedure TCustomCodeEditor.CodeCompleteApply;
  6571. var S: string;
  6572. FragLen,
  6573. I: integer;
  6574. begin
  6575. Lock;
  6576. { here should be some kind or "mark" or "break" inserted in the Undo
  6577. information, so activating it "undoes" only the completition first and
  6578. doesn't delete the complete word at once... - Gabor }
  6579. FragLen:=Length(GetCodeCompleteFrag);
  6580. S:=GetCodeCompleteWord;
  6581. for I:=FragLen+1 to length(S) do
  6582. AddChar(S[I]);
  6583. UnLock;
  6584. SetCompleteState(csInactive);
  6585. end;
  6586. procedure TCustomCodeEditor.CodeCompleteCancel;
  6587. begin
  6588. SetCompleteState(csDenied);
  6589. end;
  6590. procedure TCustomCodeEditor.CodeCompleteCheck;
  6591. var Line: string;
  6592. X: sw_integer;
  6593. CurWord,NewWord: string;
  6594. begin
  6595. SetCodeCompleteFrag('');
  6596. if (not IsFlagSet(efCodeComplete)) or (IsReadOnly=true) then Exit;
  6597. Lock;
  6598. Line:=GetDisplayText(CurPos.Y);
  6599. X:=CurPos.X; CurWord:='';
  6600. if X<=length(Line) then
  6601. while (X>0) and (Line[X] in (NumberChars+AlphaChars)) do
  6602. begin
  6603. CurWord:=Line[X]+CurWord;
  6604. Dec(X);
  6605. end;
  6606. if (length(CurWord)>=CodeCompleteMinLen) and CompleteCodeWord(CurWord,NewWord) then
  6607. begin
  6608. SetCodeCompleteFrag(CurWord);
  6609. SetCodeCompleteWord(NewWord);
  6610. end
  6611. else
  6612. ClearCodeCompleteWord;
  6613. UnLock;
  6614. end;
  6615. function TCustomCodeEditor.GetCodeCompleteFrag: string;
  6616. begin
  6617. { Abstract }
  6618. GetCodeCompleteFrag:='';
  6619. end;
  6620. procedure TCustomCodeEditor.SetCodeCompleteFrag(const S: string);
  6621. begin
  6622. { Abstract }
  6623. end;
  6624. procedure TCustomCodeEditor.DrawLines(FirstLine: sw_integer);
  6625. begin
  6626. if FirstLine>=(Delta.Y+Size.Y) then Exit; { falls outside of the screen }
  6627. DrawView;
  6628. end;
  6629. procedure TCustomCodeEditor.HideHighlight;
  6630. begin
  6631. SetHighlight(CurPos,CurPos);
  6632. end;
  6633. function TCustomCodeEditor.InSelectionArea:boolean; {CurPos in selection area}
  6634. begin
  6635. InSelectionArea:=false;
  6636. if ((SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y)) then {there is selection}
  6637. begin
  6638. if (SelStart.Y = SelEnd.Y) and (CurPos.X>=min(SelStart.X,SelEnd.X)) and (CurPos.X<=max(SelStart.X,SelEnd.X)) then
  6639. InSelectionArea:=true {select in one line}
  6640. else if (CurPos.Y>min(SelStart.Y,SelEnd.Y)) and (CurPos.Y<max(SelStart.Y,SelEnd.Y)) then
  6641. InSelectionArea:=true {between first and last selected line}
  6642. 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
  6643. InSelectionArea:=true {in first line or last line}
  6644. 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
  6645. InSelectionArea:=true; {in first line or last line (selection Start and End revers)}
  6646. end;
  6647. end;
  6648. procedure TCustomCodeEditor.GetSelectionArea(var StartP,EndP: TPoint);
  6649. begin
  6650. StartP:=SelStart; EndP:=SelEnd;
  6651. if EndP.X=0 then
  6652. begin
  6653. Dec(EndP.Y);
  6654. EndP.X:=length(GetDisplayText(EndP.Y))-1;
  6655. end
  6656. else
  6657. Dec(EndP.X);
  6658. end;
  6659. function TCustomCodeEditor.ValidBlock: boolean;
  6660. begin
  6661. ValidBlock:=(SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y);
  6662. end;
  6663. procedure TCustomCodeEditor.SetSelection(A, B: TPoint);
  6664. var WV: boolean;
  6665. OS,OE: TPoint;
  6666. begin
  6667. WV:=ValidBlock;
  6668. OS:=SelStart; OE:=SelEnd;
  6669. SelStart:=A; SelEnd:=B;
  6670. if (WV=false) and (ValidBlock=false) then { do nothing } else
  6671. if (OS.X<>SelStart.X) or (OS.Y<>SelStart.Y) or
  6672. (OE.X<>SelEnd.X) or (OE.Y<>SelEnd.Y) then
  6673. SelectionChanged;
  6674. end;
  6675. procedure TCustomCodeEditor.SetHighlight(A, B: TPoint);
  6676. begin
  6677. Highlight.A:=A; Highlight.B:=B;
  6678. HighlightChanged;
  6679. end;
  6680. {procedure TCustomCodeEditor.SetHighlightRow(Row: sw_integer);
  6681. begin
  6682. HighlightRow:=Row;
  6683. DrawView;
  6684. end;}
  6685. {procedure TCodeEditor.SetDebuggerRow(Row: sw_integer);
  6686. begin
  6687. DebuggerRow:=Row;
  6688. DrawView;
  6689. end;}
  6690. procedure TCustomCodeEditor.SelectAll(Enable: boolean);
  6691. var A,B: TPoint;
  6692. begin
  6693. if (Enable=false) or (GetLineCount=0) then
  6694. begin A:=CurPos; B:=CurPos end
  6695. else
  6696. begin
  6697. A.X:=0; A.Y:=0;
  6698. { B.Y:=GetLineCount-1;
  6699. B.X:=length(GetLineText(B.Y));}
  6700. B.Y:=GetLineCount; B.X:=0;
  6701. end;
  6702. SetSelection(A,B);
  6703. DrawView;
  6704. end;
  6705. procedure TCustomCodeEditor.SelectionChanged;
  6706. var Enable,CanPaste: boolean;
  6707. begin
  6708. if GetLineCount=0 then
  6709. begin
  6710. SelStart.X:=0; SelStart.Y:=0; SelEnd:=SelStart;
  6711. end
  6712. else
  6713. if SelEnd.Y>GetLineCount-1 then
  6714. if (SelEnd.Y<>GetLineCount) or (SelEnd.X<>0) then
  6715. begin
  6716. SelEnd.Y:=GetLineCount-1;
  6717. SelEnd.X:=length(GetDisplayText(SelEnd.Y));
  6718. end;
  6719. { we change the CurCommandSet, but only if we are top view }
  6720. if ((State and sfFocused)<>0) then
  6721. begin
  6722. Enable:=((SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y)) and (Clipboard<>nil);
  6723. SetCmdState(ToClipCmds,Enable and (Clipboard<>@Self));
  6724. SetCmdState(NulClipCmds,Enable);
  6725. CanPaste:=(Clipboard<>nil) and ((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
  6726. (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
  6727. SetCmdState(FromClipCmds,CanPaste and (Clipboard<>@Self));
  6728. SetCmdState(UndoCmd,(GetUndoActionCount>0));
  6729. SetCmdState(RedoCmd,(GetRedoActionCount>0));
  6730. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  6731. end;
  6732. DrawView;
  6733. end;
  6734. procedure TCustomCodeEditor.HighlightChanged;
  6735. begin
  6736. DrawView;
  6737. end;
  6738. procedure TCustomCodeEditor.SetState(AState: Word; Enable: Boolean);
  6739. procedure ShowSBar(SBar: PScrollBar);
  6740. begin
  6741. if Assigned(SBar) and (SBar^.GetState(sfVisible)=false) then
  6742. SBar^.Show;
  6743. end;
  6744. begin
  6745. inherited SetState(AState,Enable);
  6746. if AlwaysShowScrollBars then
  6747. begin
  6748. ShowSBar(HScrollBar);
  6749. ShowSBar(VScrollBar);
  6750. end;
  6751. if (AState and (sfActive+sfSelected+sfFocused))<>0 then
  6752. begin
  6753. SelectionChanged;
  6754. if ((State and sfFocused)=0) and (GetCompleteState=csOffering) then
  6755. ClearCodeCompleteWord;
  6756. end;
  6757. end;
  6758. function TCustomCodeEditor.GetPalette: PPalette;
  6759. const P: string[length(CEditor)] = CEditor;
  6760. begin
  6761. GetPalette:=@P;
  6762. end;
  6763. function TCustomCodeEditorCore.LoadFromStream(Editor: PCustomCodeEditor; Stream: PFastBufStream): boolean;
  6764. var S: sw_AString;
  6765. AllLinesComplete,LineComplete,hasCR,OK: boolean;
  6766. begin
  6767. DeleteAllLines;
  6768. ChangedLine:=-1;
  6769. AllLinesComplete:=true;
  6770. OK:=(Stream^.Status=stOK);
  6771. if eofstream(Stream) then
  6772. AddLine('')
  6773. else
  6774. begin
  6775. while OK and (eofstream(Stream)=false) and (GetLineCount<MaxLineCount) do
  6776. begin
  6777. if not UseOldBufStreamMethod then
  6778. Stream^.Readline(S,LineComplete,hasCR)
  6779. else
  6780. ReadlnFromStream(Stream,S,LineComplete,hasCR);
  6781. AllLinesComplete:=AllLinesComplete and LineComplete;
  6782. OK:=OK and (Stream^.Status=stOK);
  6783. if OK then AddLine(S);
  6784. if not LineComplete and (ChangedLine=-1) then
  6785. ChangedLine:=GetLineCount;
  6786. end;
  6787. { Do not remove the final newline if it exists PM }
  6788. if hasCR then
  6789. AddLine('');
  6790. end;
  6791. LimitsChanged;
  6792. if not AllLinesComplete then
  6793. SetModified(true);
  6794. if (GetLineCount=MaxLineCount) and not eofstream(stream) then
  6795. EditorDialog(edTooManyLines,nil);
  6796. LoadFromStream:=OK;
  6797. end;
  6798. function TCustomCodeEditorCore.SaveAreaToStream(Editor: PCustomCodeEditor; Stream: PStream; StartP,EndP: TPoint): boolean;
  6799. var S: sw_astring;
  6800. OK: boolean;
  6801. Line: Sw_integer;
  6802. begin
  6803. if EndP.X=0 then
  6804. begin
  6805. if EndP.Y>0 then
  6806. begin
  6807. EndP.X:=length(GetDisplayText(EndP.Y));
  6808. end
  6809. else
  6810. EndP.X:=0;
  6811. end
  6812. else
  6813. Dec(EndP.X);
  6814. OK:=(Stream^.Status=stOK); Line:=StartP.Y;
  6815. while OK and (Line<=EndP.Y) and (Line<GetLineCount) do
  6816. begin
  6817. S:=GetLineText(Line);
  6818. { Remove all traling spaces PM }
  6819. if not Editor^.IsFlagSet(efKeepTrailingSpaces) then
  6820. s:=RTrim(S,False); // removes trailing #0 too
  6821. { if FlagSet(efUseTabCharacters) then
  6822. S:=CompressUsingTabs(S,TabSize);
  6823. }
  6824. if Line=EndP.Y then S:=copy(S,1,LinePosToCharIdx(Line,EndP.X));
  6825. if Line=StartP.Y then S:=copy(S,LinePosToCharIdx(Line,StartP.X),Length(S));
  6826. Stream^.Write(S[1],length(S));
  6827. if Line<EndP.Y then
  6828. Stream^.Write(EOL[1],length(EOL));
  6829. Inc(Line);
  6830. OK:=OK and (Stream^.Status=stOK);
  6831. end;
  6832. SaveAreaToStream:=OK;
  6833. end;
  6834. constructor TEditorAction.init(act:byte; StartP,EndP:TPoint;Txt:Sw_AString;AFlags : longint);
  6835. begin
  6836. Action:=act;
  6837. StartPos:=StartP;
  6838. EndPos:=EndP;
  6839. SetText(Txt);
  6840. ActionCount:=0;
  6841. Flags:=AFlags;
  6842. TimeStamp:=Now;
  6843. IsGrouped:=false;
  6844. end;
  6845. constructor TEditorAction.init_group(act:byte);
  6846. begin
  6847. Action:=act;
  6848. ActionCount:=0;
  6849. Flags:=0;
  6850. IsGrouped:=true;
  6851. end;
  6852. function TEditorAction.Is_grouped_action : boolean;
  6853. begin
  6854. Is_grouped_action:=IsGrouped;
  6855. end;
  6856. function TEditorAction.GetText : sw_astring;
  6857. var st : string;
  6858. begin
  6859. {$if sizeof(sw_astring)>8}
  6860. GetText:=GetStr(Text);
  6861. {$else}
  6862. GetText:=Text;
  6863. {$endif}
  6864. end;
  6865. procedure TEditorAction.SetText(AText : sw_astring);
  6866. var st : string;
  6867. begin
  6868. {$if sizeof(sw_astring)>8}
  6869. SetStr(Text,AText);
  6870. {$else}
  6871. Text:=AText;
  6872. {$endif}
  6873. end;
  6874. destructor TEditorAction.done;
  6875. begin
  6876. {$if sizeof(sw_astring)>8}
  6877. if assigned(Text) then
  6878. DisposeStr(Text);
  6879. Text:=nil;
  6880. {$else}
  6881. Text:='';
  6882. {$endif}
  6883. inherited done;
  6884. end;
  6885. function TEditorActionCollection.At(Idx : sw_integer) : PEditorAction;
  6886. begin
  6887. At:=PEditorAction(Inherited At(Idx));
  6888. end;
  6889. procedure TEditorInputLine.HandleEvent(var Event : TEvent);
  6890. var
  6891. s : sw_astring;
  6892. st : string; {need to be shortstring for InputLine}
  6893. i : longint;
  6894. begin
  6895. If (Event.What=evKeyDown) then
  6896. begin
  6897. if (Event.KeyCode=kbRight) and
  6898. (CurPos = Length(Data^)) and
  6899. Assigned(FindReplaceEditor) then
  6900. Begin
  6901. s:=FindReplaceEditor^.GetDisplayText(FindReplaceEditor^.CurPos.Y);
  6902. i:=Min(FindReplaceEditor^.CurPos.X+1,length(s));
  6903. {finds beginning of word}
  6904. if i>0 then
  6905. while s[i] in ['a'..'z','A'..'Z','0'..'9','_'] do
  6906. begin
  6907. dec(i);
  6908. if i=0 then break;
  6909. end;
  6910. inc(i);
  6911. {step out of white space}
  6912. if i<length(s) then
  6913. while (s[i] in [' ']) do
  6914. begin
  6915. inc(i);
  6916. if i=length(s) then break;
  6917. end;
  6918. st:=Copy(s,i-length(Data^),length(s)-(i-length(Data^))+1);
  6919. if length(Data^)=0 then
  6920. i:=1 {if input line is empty then start from first character of word if any}
  6921. else
  6922. i:=pos(Data^,st);
  6923. if (i>0) and (length(st)>=i+length(Data^)) then
  6924. begin
  6925. st:=Data^+st[i+length(Data^)];
  6926. If not assigned(validator) or
  6927. Validator^.IsValidInput(st,False) then
  6928. Begin
  6929. Event.CharCode:=st[length(st)];
  6930. Event.Scancode:=0;
  6931. Inherited HandleEvent(Event);
  6932. End;
  6933. end;
  6934. ClearEvent(Event);
  6935. End
  6936. else if ((Event.KeyCode=kbShiftIns) or (Event.KeyCode=paste_key)) and
  6937. Assigned(Clipboard) and (Clipboard^.ValidBlock) then
  6938. { paste from clipboard }
  6939. begin
  6940. i:=Clipboard^.SelStart.Y;
  6941. s:=Clipboard^.GetDisplayText(i);
  6942. i:=Clipboard^.SelStart.X;
  6943. if i>0 then
  6944. s:=copy(s,i+1,length(s));
  6945. if (Clipboard^.SelStart.Y=Clipboard^.SelEnd.Y) then
  6946. begin
  6947. i:=Clipboard^.SelEnd.X-i;
  6948. s:=copy(s,1,i);
  6949. end;
  6950. for i:=1 to length(s) do
  6951. begin
  6952. st:=Data^+s[i];
  6953. If not assigned(validator) or
  6954. Validator^.IsValidInput(st,False) then
  6955. Begin
  6956. Event.What:=evKeyDown;
  6957. Event.CharCode:=s[i];
  6958. Event.Scancode:=0;
  6959. Inherited HandleEvent(Event);
  6960. End;
  6961. end;
  6962. ClearEvent(Event);
  6963. end
  6964. else if ((Event.KeyCode=kbCtrlIns) or (Event.KeyCode=copy_key)) and
  6965. Assigned(Clipboard) then
  6966. { Copy to clipboard }
  6967. begin
  6968. s:=GetStr(Data);
  6969. s:=copy(s,selstart+1,selend-selstart);
  6970. Clipboard^.SelStart:=Clipboard^.CurPos;
  6971. Clipboard^.InsertText(s);
  6972. Clipboard^.SelEnd:=Clipboard^.CurPos;
  6973. ClearEvent(Event);
  6974. end
  6975. else if ((Event.KeyCode=kbShiftDel) or (Event.KeyCode=cut_key)) and
  6976. Assigned(Clipboard) then
  6977. { Cut to clipboard }
  6978. begin
  6979. s:=GetStr(Data);
  6980. s:=copy(s,selstart+1,selend-selstart);
  6981. Clipboard^.SelStart:=Clipboard^.CurPos;
  6982. Clipboard^.InsertText(s);
  6983. Clipboard^.SelEnd:=Clipboard^.CurPos;
  6984. { now remove the selected part }
  6985. Event.keyCode:=kbDel;
  6986. inherited HandleEvent(Event);
  6987. ClearEvent(Event);
  6988. end
  6989. else if ((Event.KeyCode=kbCtrlDel)) then
  6990. { Cut & discard }
  6991. begin
  6992. { now remove the selected part }
  6993. Event.keyCode:=kbDel;
  6994. inherited HandleEvent(Event);
  6995. ClearEvent(Event);
  6996. end
  6997. else
  6998. Inherited HandleEvent(Event);
  6999. End
  7000. else
  7001. Inherited HandleEvent(Event);
  7002. st:=getstr(data);
  7003. Message(Owner,evBroadCast,cmInputLineLen,pointer(Length(st)));
  7004. end;
  7005. constructor TFPFileInputLine.Init(var Bounds: TRect; AMaxLen: Sw_Integer);
  7006. begin
  7007. inherited Init(Bounds, AMaxLen);
  7008. end;
  7009. procedure TFPFileInputLine.HandleEvent(var Event: TEvent);
  7010. var s : sw_astring;
  7011. i : sw_integer;
  7012. st: string;
  7013. begin
  7014. If (Event.What=evKeyDown) then
  7015. begin
  7016. if ((Event.KeyCode=kbShiftIns) or (Event.KeyCode=paste_key)) and
  7017. Assigned(weditor.Clipboard) and (weditor.Clipboard^.ValidBlock) then
  7018. { paste from clipboard }
  7019. begin
  7020. i:=Clipboard^.SelStart.Y;
  7021. s:=Clipboard^.GetDisplayText(i);
  7022. i:=Clipboard^.SelStart.X;
  7023. if i>0 then
  7024. s:=copy(s,i+1,length(s));
  7025. if (Clipboard^.SelStart.Y=Clipboard^.SelEnd.Y) then
  7026. begin
  7027. i:=Clipboard^.SelEnd.X-i;
  7028. s:=copy(s,1,i);
  7029. end;
  7030. for i:=1 to length(s) do
  7031. begin
  7032. st:=Data^+s[i];
  7033. If not assigned(validator) or
  7034. Validator^.IsValidInput(st,False) then
  7035. Begin
  7036. Event.What:=evKeyDown;
  7037. Event.CharCode:=s[i];
  7038. Event.Scancode:=0;
  7039. Inherited HandleEvent(Event);
  7040. End;
  7041. end;
  7042. ClearEvent(Event);
  7043. end
  7044. else if ((Event.KeyCode=kbCtrlIns) or (Event.KeyCode=copy_key)) and
  7045. Assigned(Clipboard) then
  7046. { Copy to clipboard }
  7047. begin
  7048. s:=GetStr(Data);
  7049. s:=copy(s,selstart+1,selend-selstart);
  7050. Clipboard^.SelStart:=Clipboard^.CurPos;
  7051. Clipboard^.InsertText(s);
  7052. Clipboard^.SelEnd:=Clipboard^.CurPos;
  7053. ClearEvent(Event);
  7054. end
  7055. else if ((Event.KeyCode=kbShiftDel) or (Event.KeyCode=cut_key)) and
  7056. Assigned(Clipboard) then
  7057. { Cut to clipboard }
  7058. begin
  7059. s:=GetStr(Data);
  7060. s:=copy(s,selstart+1,selend-selstart);
  7061. Clipboard^.SelStart:=Clipboard^.CurPos;
  7062. Clipboard^.InsertText(s);
  7063. Clipboard^.SelEnd:=Clipboard^.CurPos;
  7064. { now remove the selected part }
  7065. Event.keyCode:=kbDel;
  7066. inherited HandleEvent(Event);
  7067. ClearEvent(Event);
  7068. end
  7069. else if ((Event.KeyCode=kbCtrlDel)) then
  7070. { Cut & discard }
  7071. begin
  7072. { now remove the selected part }
  7073. Event.keyCode:=kbDel;
  7074. inherited HandleEvent(Event);
  7075. ClearEvent(Event);
  7076. end
  7077. else
  7078. Inherited HandleEvent(Event);
  7079. End
  7080. else
  7081. Inherited HandleEvent(Event);
  7082. //st:=getstr(data);
  7083. //Message(Owner,evBroadCast,cmInputLineLen,pointer(Length(st)));
  7084. end;
  7085. constructor TFPFileDialog.Init(AWildCard: TWildStr; const ATitle,
  7086. InputName: String; AOptions: Word; HistoryId: Byte);
  7087. var R: TRect;
  7088. DInput : PFPFileInputLine;
  7089. Control : PView;
  7090. History : PHistory;
  7091. S : String;
  7092. begin
  7093. inherited init(AWildCard,ATitle,InputName,AOptions,HistoryId);
  7094. FileName^.getData(S);
  7095. R.Assign(3, 3, 31, 4);
  7096. DInput := New(PFPFileInputLine, Init(R, 79{FileNameLen+4}));
  7097. DInput^.SetData(S);
  7098. InsertBefore(DInput,FileName); {insert before to preserv order as it was}
  7099. Delete(FileName);
  7100. Dispose(FileName,done);
  7101. DInput^.GrowMode:=gfGrowHiX;
  7102. FileName:=DInput;
  7103. FileHistory^.Link:=DInput;
  7104. {resize}
  7105. if Desktop^.Size.Y > 26 then
  7106. GrowTo(Size.X,Desktop^.Size.Y-6);
  7107. if Desktop^.Size.X > 80 then
  7108. GrowTo(Min(Desktop^.Size.X-(80-Size.X),102),Size.Y);
  7109. FileList^.NumCols:= Max((FileList^.Size.X-(FileList^.Size.X div 14)) div 14,2);
  7110. {set focus on the new input line}
  7111. DInput^.Focus;
  7112. end;
  7113. procedure TSearchHelperDialog.HandleEvent(var Event : TEvent);
  7114. begin
  7115. case Event.What of
  7116. evBroadcast :
  7117. case Event.Command of
  7118. cminputlinelen : begin
  7119. if PtrInt(Event.InfoPtr)=0 then
  7120. okbutton^.DisableCommands([cmok])
  7121. else
  7122. okbutton^.EnableCommands([cmok]);
  7123. clearevent(event);
  7124. end;
  7125. end;
  7126. end;
  7127. inherited HandleEvent(Event);
  7128. end;
  7129. function CreateFindDialog: PDialog;
  7130. var R,R1,R2: TRect;
  7131. D: PSearchHelperDialog;
  7132. IL1: PEditorInputLine;
  7133. Control : PView;
  7134. CB1: PCheckBoxes;
  7135. RB1,RB2,RB3: PRadioButtons;
  7136. but : PButton;
  7137. begin
  7138. R.Assign(0,0,56,15);
  7139. New(D, Init(R, dialog_find));
  7140. with D^ do
  7141. begin
  7142. Options:=Options or ofCentered;
  7143. GetExtent(R); R.Grow(-3,-2);
  7144. R1.Copy(R); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  7145. R2.Copy(R); R2.B.X:=R2.B.X-3;R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  7146. New(IL1, Init(R2, FindStrSize));
  7147. IL1^.Data^:=FindStr;
  7148. Insert(IL1);
  7149. Insert(New(PLabel, Init(R1, label_find_texttofind, IL1)));
  7150. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  7151. Control := New(PHistory, Init(R1, IL1, TextFindId));
  7152. Insert(Control);
  7153. 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;
  7154. R2.Copy(R1); R2.Move(0,1);
  7155. R2.B.Y:=R2.A.Y+{$ifdef TEST_REGEXP}3{$else}2{$endif};
  7156. New(CB1, Init(R2,
  7157. NewSItem(label_find_casesensitive,
  7158. NewSItem(label_find_wholewordsonly,
  7159. {$ifdef TEST_REGEXP}
  7160. NewSItem(label_find_useregexp,
  7161. {$endif TEST_REGEXP}
  7162. nil)))){$ifdef TEST_REGEXP}){$endif TEST_REGEXP};
  7163. Insert(CB1);
  7164. Insert(New(PLabel, Init(R1, label_find_options, CB1)));
  7165. 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;
  7166. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7167. New(RB1, Init(R2,
  7168. NewSItem(label_find_forward,
  7169. NewSItem(label_find_backward,
  7170. nil))));
  7171. Insert(RB1);
  7172. Insert(New(PLabel, Init(R1, label_find_direction, RB1)));
  7173. 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;
  7174. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7175. New(RB2, Init(R2,
  7176. NewSItem(label_find_global,
  7177. NewSItem(label_find_selectedtext,
  7178. nil))));
  7179. Insert(RB2);
  7180. Insert(New(PLabel, Init(R1, label_find_scope, RB2)));
  7181. 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;
  7182. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7183. New(RB3, Init(R2,
  7184. NewSItem(label_find_fromcursor,
  7185. NewSItem(label_find_entirescope,
  7186. nil))));
  7187. Insert(RB3);
  7188. Insert(New(PLabel, Init(R1, label_find_origin, RB3)));
  7189. GetExtent(R); R.Grow(-13,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10;
  7190. Okbutton:=New(PButton, Init(R, btn_OK, cmOK, bfDefault));
  7191. Insert(OkButton);
  7192. R.Move(19,0);
  7193. Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
  7194. end;
  7195. IL1^.Select;
  7196. CreateFindDialog := D;
  7197. end;
  7198. function CreateReplaceDialog: PDialog;
  7199. var R,R1,R2: TRect;
  7200. D: PDialog;
  7201. Control : PView;
  7202. IL1: PEditorInputLine;
  7203. IL2: PEditorInputLine;
  7204. CB1: PCheckBoxes;
  7205. RB1,RB2,RB3: PRadioButtons;
  7206. begin
  7207. R.Assign(0,0,56,18);
  7208. New(D, Init(R, dialog_replace));
  7209. with D^ do
  7210. begin
  7211. Options:=Options or ofCentered;
  7212. GetExtent(R); R.Grow(-3,-2);
  7213. R1.Copy(R); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  7214. R2.Copy(R); R2.B.X:=R2.B.X-3;R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  7215. New(IL1, Init(R2, FindStrSize));
  7216. IL1^.Data^:=FindStr;
  7217. Insert(IL1);
  7218. Insert(New(PLabel, Init(R1, label_replace_texttofind, IL1)));
  7219. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  7220. Control := New(PHistory, Init(R1, IL1, TextFindId));
  7221. Insert(Control);
  7222. R1.Copy(R); R1.Move(0,2); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  7223. R2.Copy(R); R2.Move(0,2);R2.B.X:=R2.B.X-3;
  7224. R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  7225. New(IL2, Init(R2, FindStrSize));
  7226. IL2^.Data^:=ReplaceStr;
  7227. Insert(IL2);
  7228. Insert(New(PLabel, Init(R1, label_replace_newtext, IL2)));
  7229. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  7230. Control := New(PHistory, Init(R1, IL2, TextReplaceId));
  7231. Insert(Control);
  7232. 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;
  7233. R2.Copy(R1); R2.Move(0,1);
  7234. R2.B.Y:=R2.A.Y+{$ifdef TEST_REGEXP}4{$else}3{$endif};
  7235. New(CB1, Init(R2,
  7236. NewSItem(label_replace_casesensitive,
  7237. NewSItem(label_replace_wholewordsonly,
  7238. NewSItem(label_replace_promptonreplace,
  7239. {$ifdef TEST_REGEXP}
  7240. NewSItem(label_find_useregexp,
  7241. {$endif TEST_REGEXP}
  7242. nil))))){$ifdef TEST_REGEXP}){$endif TEST_REGEXP};
  7243. Insert(CB1);
  7244. Insert(New(PLabel, Init(R1, label_replace_options, CB1)));
  7245. 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;
  7246. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7247. New(RB1, Init(R2,
  7248. NewSItem(label_replace_forward,
  7249. NewSItem(label_replace_backward,
  7250. nil))));
  7251. Insert(RB1);
  7252. Insert(New(PLabel, Init(R1, label_replace_direction, RB1)));
  7253. 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;
  7254. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7255. New(RB2, Init(R2,
  7256. NewSItem(label_replace_global,
  7257. NewSItem(label_replace_selectedtext,
  7258. nil))));
  7259. Insert(RB2);
  7260. Insert(New(PLabel, Init(R1, label_replace_scope, RB2)));
  7261. 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;
  7262. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  7263. New(RB3, Init(R2,
  7264. NewSItem(label_replace_fromcursor,
  7265. NewSItem(label_replace_entirescope,
  7266. nil))));
  7267. Insert(RB3);
  7268. Insert(New(PLabel, Init(R1, label_replace_origin, RB3)));
  7269. GetExtent(R); R.Grow(-13,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10; R.Move(-10,0);
  7270. Insert(New(PButton, Init(R, btn_OK, cmOK, bfDefault)));
  7271. R.Move(11,0); R.B.X:=R.A.X+14;
  7272. Insert(New(PButton, Init(R, btn_replace_changeall, cmYes, bfNormal)));
  7273. R.Move(15,0); R.B.X:=R.A.X+10;
  7274. Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
  7275. end;
  7276. IL1^.Select;
  7277. CreateReplaceDialog := D;
  7278. end;
  7279. function CreateGotoLineDialog(Info: pointer): PDialog;
  7280. var D: PDialog;
  7281. R,R1,R2: TRect;
  7282. Control : PView;
  7283. IL: PEditorInputLine;
  7284. begin
  7285. R.Assign(0,0,40,7);
  7286. New(D, Init(R, dialog_gotoline));
  7287. with D^ do
  7288. begin
  7289. Options:=Options or ofCentered;
  7290. GetExtent(R); R.Grow(-3,-2); R.B.Y:=R.A.Y+1;
  7291. R1.Copy(R); R1.B.X:=27; R2.Copy(R);
  7292. R2.B.X:=R2.B.X-3;R2.A.X:=27;
  7293. New(IL, Init(R2,5));
  7294. with TGotoLineDialogRec(Info^) do
  7295. IL^.SetValidator(New(PRangeValidator, Init(1, Lines)));
  7296. Insert(IL);
  7297. Insert(New(PLabel, Init(R1, label_gotoline_linenumber, IL)));
  7298. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  7299. Control := New(PHistory, Init(R1, IL, GotoId));
  7300. Insert(Control);
  7301. GetExtent(R); R.Grow(-8,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10;
  7302. Insert(New(PButton, Init(R, btn_OK, cmOK, bfDefault)));
  7303. R.Move(15,0);
  7304. Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
  7305. end;
  7306. IL^.Select;
  7307. CreateGotoLineDialog:=D;
  7308. end;
  7309. function StdEditorDialog(Dialog: Integer; Info: Pointer): Word;
  7310. var
  7311. R: TRect;
  7312. T: TPoint;
  7313. Re: word;
  7314. Name: string;
  7315. DriveNumber : byte;
  7316. StoreDir,StoreDir2 : DirStr;
  7317. Title,DefExt: string;
  7318. AskOW: boolean;
  7319. begin
  7320. case Dialog of
  7321. edOutOfMemory:
  7322. StdEditorDialog := AdvMessageBox(msg_notenoughmemoryforthisoperation,
  7323. nil, mfInsertInApp+ mfError + mfOkButton);
  7324. edReadError:
  7325. StdEditorDialog := AdvMessageBox(msg_errorreadingfile,
  7326. @Info, mfInsertInApp+ mfError + mfOkButton);
  7327. edWriteError:
  7328. StdEditorDialog := AdvMessageBox(msg_errorwritingfile,
  7329. @Info, mfInsertInApp+ mfError + mfOkButton);
  7330. edSaveError:
  7331. StdEditorDialog := AdvMessageBox(msg_errorsavingfile,
  7332. @Info, mfInsertInApp+ mfError + mfOkButton);
  7333. edCreateError:
  7334. StdEditorDialog := AdvMessageBox(msg_errorcreatingfile,
  7335. @Info, mfInsertInApp+ mfError + mfOkButton);
  7336. edSaveModify:
  7337. StdEditorDialog := AdvMessageBox(msg_filehasbeenmodifiedsave,
  7338. @Info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7339. edSaveUntitled:
  7340. StdEditorDialog := AdvMessageBox(msg_saveuntitledfile,
  7341. nil, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7342. edChangedOnloading:
  7343. StdEditorDialog := AdvMessageBox(msg_filehadtoolonglines,
  7344. Info, mfInsertInApp+ mfOKButton + mfInformation);
  7345. edFileOnDiskChanged:
  7346. StdEditorDialog := AdvMessageBox(msg_filewasmodified,
  7347. @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7348. edReloadDiskmodifiedFile:
  7349. StdEditorDialog := AdvMessageBox(msg_reloaddiskmodifiedfile,
  7350. @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7351. edReloadDiskAndIDEModifiedFile:
  7352. StdEditorDialog := AdvMessageBox(msg_reloaddiskandidemodifiedfile,
  7353. @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  7354. edSaveAs,edWriteBlock,edReadBlock:
  7355. begin
  7356. Name:=PString(Info)^;
  7357. GetDir(0,StoreDir);
  7358. DriveNumber:=0;
  7359. if (Length(FileDir)>1) and (FileDir[2]=':') then
  7360. begin
  7361. { does not assume that lowercase are greater then uppercase ! }
  7362. if (FileDir[1]>='a') and (FileDir[1]<='z') then
  7363. DriveNumber:=Ord(FileDir[1])-ord('a')+1
  7364. else
  7365. DriveNumber:=Ord(FileDir[1])-ord('A')+1;
  7366. GetDir(DriveNumber,StoreDir2);
  7367. {$I-}
  7368. ChDir(Copy(FileDir,1,2));
  7369. EatIO;
  7370. {$I+}
  7371. end;
  7372. if FileDir<>'' then
  7373. begin
  7374. {$I-}
  7375. ChDir(TrimEndSlash(FileDir));
  7376. EatIO;
  7377. {$I+}
  7378. end;
  7379. case Dialog of
  7380. edSaveAs :
  7381. begin
  7382. Title:=dialog_savefileas;
  7383. DefExt:='*'+DefaultSaveExt;
  7384. end;
  7385. edWriteBlock :
  7386. begin
  7387. Title:=dialog_writeblocktofile;
  7388. DefExt:='*.*';
  7389. end;
  7390. edReadBlock :
  7391. begin
  7392. Title:=dialog_readblockfromfile;
  7393. DefExt:='*.*';
  7394. end;
  7395. else begin Title:='???'; DefExt:=''; end;
  7396. end;
  7397. Re:=Application^.ExecuteDialog(New(PFPFileDialog, Init(DefExt,
  7398. Title, label_name, fdOkButton, FileId)), @Name);
  7399. case Dialog of
  7400. edSaveAs :
  7401. begin
  7402. if ExtOf(Name)='' then
  7403. Name:=Name+DefaultSaveExt;
  7404. AskOW:=(Name<>PString(Info)^);
  7405. end;
  7406. edWriteBlock :
  7407. begin
  7408. if ExtOf(Name)='' then
  7409. Name:=Name+DefaultSaveExt;
  7410. AskOW:=true;
  7411. end;
  7412. edReadBlock : AskOW:=false;
  7413. else AskOW:=true;
  7414. end;
  7415. if (Re<>cmCancel) and AskOW then
  7416. begin
  7417. FileDir:=DirOf(FExpand(Name));
  7418. if ExistsFile(Name) then
  7419. if EditorDialog(edReplaceFile,@Name)<>cmYes then
  7420. Re:=cmCancel;
  7421. end;
  7422. if DriveNumber<>0 then
  7423. ChDir(StoreDir2);
  7424. if StoreDir<>'' then
  7425. ChDir(TrimEndSlash(StoreDir));
  7426. if Re<>cmCancel then
  7427. PString(Info)^:=Name;
  7428. StdEditorDialog := Re;
  7429. end;
  7430. edGotoLine:
  7431. StdEditorDialog :=
  7432. Application^.ExecuteDialog(CreateGotoLineDialog(Info), Info);
  7433. edFind:
  7434. StdEditorDialog :=
  7435. Application^.ExecuteDialog(CreateFindDialog, Info);
  7436. edSearchFailed:
  7437. StdEditorDialog := AdvMessageBox(msg_searchstringnotfound,
  7438. nil, mfInsertInApp+ mfError + mfOkButton);
  7439. edReplace:
  7440. StdEditorDialog :=
  7441. Application^.ExecuteDialog(CreateReplaceDialog, Info);
  7442. edReplacePrompt:
  7443. begin
  7444. { Avoid placing the dialog on the same line as the cursor }
  7445. R.Assign(0, 1, 40, 8);
  7446. R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  7447. Desktop^.MakeGlobal(R.B, T);
  7448. Inc(T.Y);
  7449. if PPoint(Info)^.Y <= T.Y then
  7450. R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  7451. StdEditorDialog := AdvMessageBoxRect(R, msg_replacethisoccourence,
  7452. nil, mfInsertInApp+ mfYesNoCancel + mfInformation);
  7453. end;
  7454. edReplaceFile :
  7455. StdEditorDialog :=
  7456. AdvMessageBox(msg_fileexistsoverwrite,@Info,mfInsertInApp+mfConfirmation+
  7457. mfYesButton+mfNoButton);
  7458. end;
  7459. end;
  7460. procedure RegisterWEditor;
  7461. begin
  7462. {$ifndef NOOBJREG}
  7463. {$endif}
  7464. end;
  7465. END.