weditor.pas 158 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998 by Berczi Gabor
  5. Code editor template objects
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$I globdir.inc}
  13. unit WEditor;
  14. interface
  15. {tes}
  16. uses
  17. Dos,Objects,Drivers,Views,Menus,Commands,
  18. WUtils;
  19. { try to only do syntax on part of file until current position
  20. does not work correctly yet PM }
  21. {$ifdef DEBUG}
  22. {$define TEST_PARTIAL_SYNTAX}
  23. {$endif DEBUG}
  24. const
  25. cmFileNameChanged = 51234;
  26. cmASCIIChar = 51235;
  27. cmClearLineHighlights = 51236;
  28. cmSaveCancelled = 51237;
  29. cmBreakLine = 51238;
  30. cmSelStart = 51239;
  31. cmSelEnd = 51240;
  32. cmLastCursorPos = 51241;
  33. cmIndentBlock = 51242;
  34. cmUnIndentBlock = 51243;
  35. cmSelectLine = 51244;
  36. cmWriteBlock = 51245;
  37. cmReadBlock = 51246;
  38. cmPrintBlock = 51247;
  39. cmResetDebuggerRow = 51248;
  40. cmAddChar = 51249;
  41. cmExpandCodeTemplate = 51250;
  42. EditorTextBufSize = {$ifdef FPC}32768{$else} 4096{$endif};
  43. MaxLineLength = {$ifdef FPC} 255{$else} 255{$endif};
  44. MaxLineCount = {$ifdef FPC}16380{$else}16380{$endif};
  45. CodeCompleteMinLen = 4; { minimum length of text to try to complete }
  46. efBackupFiles = $00000001;
  47. efInsertMode = $00000002;
  48. efAutoIndent = $00000004;
  49. efUseTabCharacters = $00000008;
  50. efBackSpaceUnindents = $00000010;
  51. efPersistentBlocks = $00000020;
  52. efSyntaxHighlight = $00000040;
  53. efBlockInsCursor = $00000080;
  54. efVerticalBlocks = $00000100;
  55. efHighlightColumn = $00000200;
  56. efHighlightRow = $00000400;
  57. efAutoBrackets = $00000800;
  58. efExpandAllTabs = $00001000;
  59. efKeepTrailingSpaces = $00002000;
  60. efCodeComplete = $00004000;
  61. efStoreContent = $80000000;
  62. attrAsm = 1;
  63. attrComment = 2;
  64. attrForceFull = 128;
  65. attrAll = attrAsm+attrComment;
  66. edOutOfMemory = 0;
  67. edReadError = 1;
  68. edWriteError = 2;
  69. edCreateError = 3;
  70. edSaveModify = 4;
  71. edSaveUntitled = 5;
  72. edSaveAs = 6;
  73. edFind = 7;
  74. edSearchFailed = 8;
  75. edReplace = 9;
  76. edReplacePrompt = 10;
  77. edTooManyLines = 11;
  78. edGotoLine = 12;
  79. edReplaceFile = 13;
  80. edWriteBlock = 14;
  81. edReadBlock = 15;
  82. edFileOnDiskChanged = 16;
  83. edChangedOnloading = 17;
  84. ffmOptions = $0007; ffsOptions = 0;
  85. ffmDirection = $0008; ffsDirection = 3;
  86. ffmScope = $0010; ffsScope = 4;
  87. ffmOrigin = $0020; ffsOrigin = 5;
  88. ffDoReplace = $0040;
  89. ffReplaceAll = $0080;
  90. ffCaseSensitive = $0001;
  91. ffWholeWordsOnly = $0002;
  92. ffPromptOnReplace = $0004;
  93. ffForward = $0000;
  94. ffBackward = $0008;
  95. ffGlobal = $0000;
  96. ffSelectedText = $0010;
  97. ffFromCursor = $0000;
  98. ffEntireScope = $0020;
  99. coTextColor = 0;
  100. coWhiteSpaceColor = 1;
  101. coCommentColor = 2;
  102. coReservedWordColor = 3;
  103. coIdentifierColor = 4;
  104. coStringColor = 5;
  105. coNumberColor = 6;
  106. coAssemblerColor = 7;
  107. coSymbolColor = 8;
  108. coDirectiveColor = 9;
  109. coHexNumberColor = 10;
  110. coTabColor = 11;
  111. coBreakColor = 12;
  112. coFirstColor = 0;
  113. coLastColor = coBreakColor;
  114. eaMoveCursor = 1;
  115. eaInsertLine = 2;
  116. eaInsertText = 3;
  117. eaDeleteLine = 4;
  118. eaDeleteText = 5;
  119. eaSelectionChanged = 6;
  120. eaCut = 7;
  121. eaPaste = 8;
  122. eaPasteWin = 9;
  123. eaClear = 10;
  124. LastAction = eaClear;
  125. ActionString : array [0..LastAction] of string[8] =
  126. ('','Move','InsLine','InsText','DelLine','DelText',
  127. 'SelCh','Cut','Paste','PasteWin','Clear');
  128. CIndicator = #2#3#1;
  129. CEditor = #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48#49;
  130. TAB = #9;
  131. FindStrSize = 79;
  132. type
  133. PLine = ^TLine;
  134. TLine = record
  135. Text : PString;
  136. Format : PString;
  137. BeginsWithAsm,
  138. EndsWithAsm : boolean;
  139. IsBreakpoint : boolean;
  140. BeginsWithComment,
  141. EndsInSingleLineComment,
  142. EndsWithComment : boolean;
  143. BeginsWithDirective,
  144. EndsWithDirective : boolean;
  145. BeginCommentType,EndCommentType : byte;
  146. end;
  147. PLineCollection = ^TLineCollection;
  148. TLineCollection = object(TCollection)
  149. function At(Index: sw_Integer): PLine;
  150. procedure FreeItem(Item: Pointer); virtual;
  151. end;
  152. PIndicator = ^TIndicator;
  153. TIndicator = object(TView)
  154. Location: TPoint;
  155. Modified : Boolean;
  156. {$ifdef debug}
  157. StoreUndo : Boolean;
  158. SyntaxComplete : boolean;
  159. UseTabs : Boolean;
  160. {$endif debug}
  161. constructor Init(var Bounds: TRect);
  162. procedure Draw; virtual;
  163. function GetPalette: PPalette; virtual;
  164. procedure SetState(AState: Word; Enable: Boolean); virtual;
  165. procedure SetValue(ALocation: TPoint; AModified: Boolean);
  166. constructor Load(var S: TStream);
  167. procedure Store(var S: TStream);
  168. end;
  169. {$ifdef Undo}
  170. PEditorAction = ^TEditorAction;
  171. TEditorAction = object(TObject)
  172. StartPos : TPoint;
  173. EndPos : TPoint;
  174. Text : PString;
  175. ActionCount : longint;
  176. Action : byte;
  177. TimeStamp : longint; { this is needed to keep track of line number &
  178. position changes (for ex. for symbol browser)
  179. the line&pos references (eg. symbol info) should
  180. also contain such a timestamp. this will enable
  181. to determine which changes have been made since
  182. storage of the information and thus calculate
  183. the (probably) changed line & position information,
  184. so, we can still jump to the right position in the
  185. editor even when it is heavily modified - Gabor }
  186. constructor init(act:byte; StartP,EndP:TPoint;Txt:String);
  187. constructor init_group(act:byte);
  188. function is_grouped_action : boolean;
  189. destructor done; virtual;
  190. end;
  191. PEditorActionCollection = ^TEditorActionCollection;
  192. TEditorActionCollection = object(TCollection)
  193. CurrentGroupedAction : PEditorAction;
  194. function At(Idx : sw_integer) : PEditorAction;
  195. end;
  196. {$else}
  197. PEditorAction = ^TEditorAction;
  198. TEditorAction = packed record
  199. StartPos : TPoint;
  200. EndPos : TPoint;
  201. Text : PString;
  202. ActionCount : longint;
  203. Action : byte;
  204. TimeStamp : longint; { see above! }
  205. end;
  206. PEditorActionCollection = ^TEditorActionCollection;
  207. TEditorActionCollection = object(TCollection)
  208. function At(Idx : sw_integer) : PEditorAction;
  209. procedure FreeItem(Item: Pointer); virtual;
  210. end;
  211. {$endif Undo}
  212. TSpecSymbolClass =
  213. (ssCommentPrefix,ssCommentSingleLinePrefix,ssCommentSuffix,ssStringPrefix,ssStringSuffix,
  214. ssDirectivePrefix,ssDirectiveSuffix,ssAsmPrefix,ssAsmSuffix);
  215. TEditorBookMark = record
  216. Valid : boolean;
  217. Pos : TPoint;
  218. end;
  219. TCompleteState = (csInactive,csOffering,csDenied);
  220. PCodeEditor = ^TCodeEditor;
  221. TCodeEditor = object(TScroller)
  222. Indicator : PIndicator;
  223. Lines : PLineCollection;
  224. SelStart : TPoint;
  225. SelEnd : TPoint;
  226. Highlight : TRect;
  227. CurPos : TPoint;
  228. CanUndo : Boolean;
  229. StoreUndo : boolean;
  230. Modified : Boolean;
  231. IsReadOnly : Boolean;
  232. NoSelect : Boolean;
  233. Flags : longint;
  234. TabSize : integer;
  235. HighlightRow: sw_integer;
  236. DebuggerRow: sw_integer;
  237. UndoList : PEditorActionCollection;
  238. RedoList : PEditorActionCollection;
  239. CompleteState: TCompleteState;
  240. CodeCompleteFrag: PString;
  241. CodeCompleteWord: PString;
  242. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  243. PScrollBar; AIndicator: PIndicator; AbufSize:Sw_Word);
  244. procedure SetFlags(AFlags: longint); virtual;
  245. procedure ConvertEvent(var Event: TEvent); virtual;
  246. procedure HandleEvent(var Event: TEvent); virtual;
  247. procedure SetState(AState: Word; Enable: Boolean); virtual;
  248. procedure LocalMenu(P: TPoint); virtual;
  249. function GetLocalMenu: PMenu; virtual;
  250. function GetCommandTarget: PView; virtual;
  251. function CreateLocalMenuView(var Bounds: TRect; M: PMenu): PMenuPopup; virtual;
  252. procedure Draw; virtual;
  253. procedure DrawCursor; virtual;
  254. procedure TrackCursor(Center: boolean); virtual;
  255. procedure UpdateIndicator; virtual;
  256. procedure LimitsChanged; virtual;
  257. procedure SelectionChanged; virtual;
  258. procedure HighlightChanged; virtual;
  259. procedure ModifiedChanged; virtual;
  260. procedure Update; virtual;
  261. procedure ScrollTo(X, Y: sw_Integer);
  262. procedure SetModified(AModified: boolean); virtual;
  263. procedure SetInsertMode(InsertMode: boolean); virtual;
  264. procedure SetCurPtr(X,Y: sw_integer); virtual;
  265. procedure SetSelection(A, B: TPoint); virtual;
  266. procedure SetHighlight(A, B: TPoint); virtual;
  267. procedure SetHighlightRow(Row: sw_integer); virtual;
  268. procedure SetDebuggerRow(Row: sw_integer); virtual;
  269. procedure SetCompleteState(AState: TCompleteState); virtual;
  270. function GetCodeCompleteFrag: string;
  271. procedure SetCodeCompleteFrag(const S: string);
  272. procedure SelectAll(Enable: boolean); virtual;
  273. function InsertFrom(Editor: PCodeEditor): Boolean; virtual;
  274. function InsertText(const S: string): Boolean; virtual;
  275. function GetPalette: PPalette; virtual;
  276. function IsClipboard: Boolean;
  277. constructor Load(var S: TStream);
  278. procedure Store(var S: TStream);
  279. function LoadFromStream(Stream: PStream): boolean; virtual;
  280. function SaveToStream(Stream: PStream): boolean; virtual;
  281. function SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
  282. destructor Done; virtual;
  283. public
  284. { Text & info storage abstraction }
  285. function GetLineCount: sw_integer; virtual;
  286. function CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
  287. function LinePosToCharIdx(Line,X: sw_integer): sw_integer;
  288. function GetLineText(I: sw_integer): string; virtual;
  289. procedure SetDisplayText(I: sw_integer;const S: string); virtual;
  290. function GetDisplayText(I: sw_integer): string; virtual;
  291. procedure SetLineText(I: sw_integer;const S: string); virtual;
  292. procedure SetLineBreakState(I : sw_integer;b : boolean);
  293. procedure GetDisplayTextFormat(I: sw_integer;var DT,DF:string); virtual;
  294. function GetLineFormat(I: sw_integer): string; virtual;
  295. procedure SetLineFormat(I: sw_integer;const S: string); virtual;
  296. procedure DeleteAllLines; virtual;
  297. procedure DeleteLine(I: sw_integer); virtual;
  298. procedure AddLine(const S: string); virtual;
  299. function GetErrorMessage: string; virtual;
  300. procedure SetErrorMessage(const S: string); virtual;
  301. procedure AdjustSelection(DeltaX, DeltaY: sw_integer);
  302. procedure AdjustSelectionPos(CurPosX, CurPosY: sw_integer; DeltaX, DeltaY: sw_integer);
  303. procedure Lock;
  304. procedure UnLock;
  305. private
  306. LastLocalCmd: word;
  307. KeyState : Integer;
  308. {$ifdef TEST_PARTIAL_SYNTAX}
  309. LastSyntaxedLine : sw_integer;
  310. SyntaxComplete : boolean;
  311. {$endif TEST_PARTIAL_SYNTAX}
  312. ChangedLine : sw_integer;
  313. ErrorMessage: PString;
  314. Bookmarks : array[0..9] of TEditorBookmark;
  315. LockFlag : integer;
  316. DrawCalled,
  317. DrawCursorCalled,
  318. IndicatorDrawCalled : boolean;
  319. CurEvent : PEvent;
  320. function Overwrite: boolean;
  321. function GetLine(I: sw_integer): PLine;
  322. procedure CheckSels;
  323. procedure CodeCompleteCheck;
  324. procedure CodeCompleteApply;
  325. procedure CodeCompleteCancel;
  326. procedure UpdateUndoRedo(cm : word; action : byte);
  327. function UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
  328. function UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
  329. procedure DrawLines(FirstLine: sw_integer);
  330. procedure HideHighlight;
  331. procedure AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string);
  332. procedure AddGroupedAction(AAction : byte);
  333. procedure CloseGroupedAction(AAction : byte);
  334. function ShouldExtend: boolean;
  335. function ValidBlock: boolean;
  336. public
  337. { Syntax highlight support }
  338. function GetSpecSymbolCount(SpecClass: TSpecSymbolClass): integer; virtual;
  339. function GetSpecSymbol(SpecClass: TSpecSymbolClass; Index: integer): string; virtual;
  340. function IsReservedWord(const S: string): boolean; virtual;
  341. { CodeTemplate support }
  342. function TranslateCodeTemplate(const Shortcut: string; ALines: PUnsortedStringCollection): boolean; virtual;
  343. { CodeComplete support }
  344. function CompleteCodeWord(const WordS: string; var Text: string): boolean; virtual;
  345. function GetCodeCompleteWord: string;
  346. procedure SetCodeCompleteWord(const S: string); virtual;
  347. procedure ClearCodeCompleteWord; virtual;
  348. public
  349. SearchRunCount: integer;
  350. InASCIIMode: boolean;
  351. procedure Indent; virtual;
  352. procedure CharLeft; virtual;
  353. procedure CharRight; virtual;
  354. procedure WordLeft; virtual;
  355. procedure WordRight; virtual;
  356. procedure LineStart; virtual;
  357. procedure LineEnd; virtual;
  358. procedure LineUp; virtual;
  359. procedure LineDown; virtual;
  360. procedure PageUp; virtual;
  361. procedure PageDown; virtual;
  362. procedure TextStart; virtual;
  363. procedure TextEnd; virtual;
  364. procedure JumpSelStart; virtual;
  365. procedure JumpSelEnd; virtual;
  366. procedure JumpMark(MarkIdx: integer); virtual;
  367. procedure DefineMark(MarkIdx: integer); virtual;
  368. procedure JumpToLastCursorPos; virtual;
  369. function InsertLine: Sw_integer; virtual;
  370. procedure BreakLine; virtual;
  371. procedure BackSpace; virtual;
  372. procedure DelChar; virtual;
  373. procedure DelWord; virtual;
  374. procedure DelStart; virtual;
  375. procedure DelEnd; virtual;
  376. procedure DelLine; virtual;
  377. procedure InsMode; virtual;
  378. procedure StartSelect; virtual;
  379. procedure EndSelect; virtual;
  380. procedure DelSelect; virtual;
  381. procedure HideSelect; virtual;
  382. procedure CopyBlock; virtual;
  383. procedure MoveBlock; virtual;
  384. procedure IndentBlock; virtual;
  385. procedure UnindentBlock; virtual;
  386. procedure SelectWord; virtual;
  387. procedure SelectLine; virtual;
  388. procedure WriteBlock; virtual;
  389. procedure ReadBlock; virtual;
  390. procedure PrintBlock; virtual;
  391. procedure ExpandCodeTemplate; virtual;
  392. procedure AddChar(C: char); virtual;
  393. {$ifdef WinClipSupported}
  394. function ClipCopyWin: Boolean; virtual;
  395. function ClipPasteWin: Boolean; virtual;
  396. {$endif WinClipSupported}
  397. function ClipCopy: Boolean; virtual;
  398. procedure ClipCut; virtual;
  399. procedure ClipPaste; virtual;
  400. function GetCurrentWord : string;
  401. procedure Undo; virtual;
  402. procedure Redo; virtual;
  403. procedure Find; virtual;
  404. procedure Replace; virtual;
  405. procedure DoSearchReplace; virtual;
  406. procedure GotoLine; virtual;
  407. end;
  408. PFileEditor = ^TFileEditor;
  409. TFileEditor = object(TCodeEditor)
  410. FileName: string;
  411. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  412. PScrollBar; AIndicator: PIndicator;const AFileName: string);
  413. function Save: Boolean; virtual;
  414. function SaveAs: Boolean; virtual;
  415. function SaveAsk: Boolean; virtual;
  416. function LoadFile: boolean; virtual;
  417. function SaveFile: boolean; virtual;
  418. function Valid(Command: Word): Boolean; virtual;
  419. procedure HandleEvent(var Event: TEvent); virtual;
  420. function ShouldSave: boolean; virtual;
  421. constructor Load(var S: TStream);
  422. procedure Store(var S: TStream);
  423. function IsChangedOnDisk : boolean;
  424. private
  425. OnDiskLoadTime : longint;
  426. end;
  427. TCodeEditorDialog = function(Dialog: Integer; Info: Pointer): Word;
  428. function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
  429. function DefUseTabsPattern(Editor: PFileEditor): boolean;
  430. const
  431. DefaultCodeEditorFlags : longint =
  432. efBackupFiles+efInsertMode+efAutoIndent+efPersistentBlocks+
  433. {efUseTabCharacters+}efBackSpaceUnindents+efSyntaxHighlight+
  434. efExpandAllTabs+efCodeComplete;
  435. DefaultTabSize : integer = 8;
  436. EOL : String[2] = {$ifdef Linux}#10;{$else}#13#10;{$endif}
  437. cmCopyWin = 240;
  438. cmPasteWin = 241;
  439. { History ID }
  440. FileId = 101;
  441. TextFindId = 105;
  442. TextReplaceID = 106;
  443. GotoID = 107;
  444. TextGrepId = 108;
  445. { used for ShiftDel and ShiftIns to avoid
  446. GetShiftState to be considered for extending
  447. selection (PM) }
  448. DontConsiderShiftState: boolean = false;
  449. ToClipCmds : TCommandSet = ([cmCut,cmCopy,cmCopyWin]);
  450. FromClipCmds : TCommandSet = ([cmPaste]);
  451. FromWinClipCmds : TCommandSet = ([cmPasteWin]);
  452. NulClipCmds : TCommandSet = ([cmClear]);
  453. UndoCmd : TCommandSet = ([cmUndo]);
  454. RedoCmd : TCommandSet = ([cmRedo]);
  455. function StdEditorDialog(Dialog: Integer; Info: Pointer): word;
  456. const
  457. EditorDialog : TCodeEditorDialog = StdEditorDialog;
  458. Clipboard : PCodeEditor = nil;
  459. FindStr : String[FindStrSize] = '';
  460. ReplaceStr : String[FindStrSize] = '';
  461. FindFlags : word = ffPromptOnReplace;
  462. WhiteSpaceChars : set of char = [#0,#32,#255];
  463. TabChars : set of char = [#9];
  464. HashChars : set of char = ['#'];
  465. AlphaChars : set of char = ['A'..'Z','a'..'z','_'];
  466. NumberChars : set of char = ['0'..'9'];
  467. RealNumberChars : set of char = ['E','e','.'{,'+','-'}];
  468. DefaultSaveExt : string[12] = '.pas';
  469. FileDir : DirStr = '';
  470. UseSyntaxHighlight : function(Editor: PFileEditor): boolean = DefUseSyntaxHighlight;
  471. UseTabsPattern : function(Editor: PFileEditor): boolean = DefUseTabsPattern;
  472. procedure RegisterCodeEditors;
  473. implementation
  474. uses
  475. MsgBox,Dialogs,App,StdDlg,HistList,Validate,
  476. {$ifdef WinClipSupported}
  477. Strings,WinClip,
  478. {$endif WinClipSupported}
  479. WViews;
  480. {$ifndef NOOBJREG}
  481. const
  482. RIndicator: TStreamRec = (
  483. ObjType: 1100;
  484. VmtLink: Ofs(TypeOf(TIndicator)^);
  485. Load: @TIndicator.Load;
  486. Store: @TIndicator.Store
  487. );
  488. RCodeEditor: TStreamRec = (
  489. ObjType: 1101;
  490. VmtLink: Ofs(TypeOf(TCodeEditor)^);
  491. Load: @TCodeEditor.Load;
  492. Store: @TCodeEditor.Store
  493. );
  494. RFileEditor: TStreamRec = (
  495. ObjType: 1102;
  496. VmtLink: Ofs(TypeOf(TFileEditor)^);
  497. Load: @TFileEditor.Load;
  498. Store: @TFileEditor.Store
  499. );
  500. {$endif}
  501. type
  502. TFindDialogRec = packed record
  503. Find : String[FindStrSize];
  504. Options : Word{longint};
  505. { checkboxes need 32 bits PM }
  506. { reverted to word in dialogs.TCluster for TP compatibility (PM) }
  507. { anyhow its complete nonsense : you can only have 16 fields
  508. but use a longint to store it !! }
  509. Direction: word;{ and tcluster has word size }
  510. Scope : word;
  511. Origin : word;
  512. end;
  513. TReplaceDialogRec = packed record
  514. Find : String[FindStrSize];
  515. Replace : String[FindStrSize];
  516. Options : Word{longint};
  517. Direction: word;
  518. Scope : word;
  519. Origin : word;
  520. end;
  521. TGotoLineDialogRec = packed record
  522. LineNo : string[5];
  523. Lines : sw_integer;
  524. end;
  525. const
  526. kbShift = kbLeftShift+kbRightShift;
  527. const
  528. FirstKeyCount = 40;
  529. FirstKeys: array[0..FirstKeyCount * 2] of Word = (FirstKeyCount,
  530. Ord(^A), cmWordLeft, Ord(^B), cmJumpLine, Ord(^C), cmPageDown,
  531. Ord(^D), cmCharRight, Ord(^E), cmLineUp,
  532. Ord(^F), cmWordRight, Ord(^G), cmDelChar,
  533. Ord(^H), cmBackSpace, Ord(^J), cmExpandCodeTemplate,
  534. Ord(^K), $FF02, Ord(^L), cmSearchAgain,
  535. Ord(^M), cmNewLine, Ord(^N), cmBreakLine,
  536. Ord(^P), cmASCIIChar, Ord(^Q), $FF01,
  537. Ord(^R), cmPageUp, Ord(^S), cmCharLeft,
  538. Ord(^T), cmDelWord, Ord(^U), cmUndo,
  539. Ord(^V), cmInsMode, Ord(^X), cmLineDown,
  540. Ord(^Y), cmDelLine, kbLeft, cmCharLeft,
  541. kbRight, cmCharRight, kbCtrlLeft, cmWordLeft,
  542. kbCtrlRight, cmWordRight, kbHome, cmLineStart,
  543. kbEnd, cmLineEnd, kbUp, cmLineUp,
  544. kbDown, cmLineDown, kbPgUp, cmPageUp,
  545. kbPgDn, cmPageDown, kbCtrlPgUp, cmTextStart,
  546. kbCtrlPgDn, cmTextEnd, kbIns, cmInsMode,
  547. kbDel, cmDelChar, kbShiftIns, cmPaste,
  548. kbShiftDel, cmCut, kbCtrlIns, cmCopy,
  549. kbCtrlDel, cmClear);
  550. QuickKeyCount = 23;
  551. QuickKeys: array[0..QuickKeyCount * 2] of Word = (QuickKeyCount,
  552. Ord('A'), cmReplace, Ord('C'), cmTextEnd,
  553. Ord('D'), cmLineEnd, Ord('F'), cmFind,
  554. Ord('H'), cmDelStart, Ord('R'), cmTextStart,
  555. Ord('S'), cmLineStart, Ord('Y'), cmDelEnd,
  556. Ord('G'), cmJumpLine, Ord('A'), cmReplace,
  557. Ord('B'), cmSelStart, Ord('K'), cmSelEnd,
  558. Ord('P'), cmLastCursorPos,
  559. Ord('0'), cmJumpMark0, Ord('1'), cmJumpMark1, Ord('2'), cmJumpMark2,
  560. Ord('3'), cmJumpMark3, Ord('4'), cmJumpMark4, Ord('5'), cmJumpMark5,
  561. Ord('6'), cmJumpMark6, Ord('7'), cmJumpMark7, Ord('8'), cmJumpMark8,
  562. Ord('9'), cmJumpMark9);
  563. BlockKeyCount = 23;
  564. BlockKeys: array[0..BlockKeyCount * 2] of Word = (BlockKeyCount,
  565. Ord('B'), cmStartSelect, Ord('C'), cmCopyBlock,
  566. Ord('H'), cmHideSelect, Ord('K'), cmEndSelect,
  567. Ord('Y'), cmDelSelect, Ord('V'), cmMoveBlock,
  568. Ord('I'), cmIndentBlock, Ord('U'), cmUnindentBlock,
  569. Ord('T'), cmSelectWord, Ord('L'), cmSelectLine,
  570. Ord('W'), cmWriteBlock, Ord('R'), cmReadBlock,
  571. Ord('P'), cmPrintBlock,
  572. Ord('0'), cmSetMark0, Ord('1'), cmSetMark1, Ord('2'), cmSetMark2,
  573. Ord('3'), cmSetMark3, Ord('4'), cmSetMark4, Ord('5'), cmSetMark5,
  574. Ord('6'), cmSetMark6, Ord('7'), cmSetMark7, Ord('8'), cmSetMark8,
  575. Ord('9'), cmSetMark9);
  576. KeyMap: array[0..2] of Pointer = (@FirstKeys, @QuickKeys, @BlockKeys);
  577. function ScanKeyMap(KeyMap: Pointer; KeyCode: Word): Word;
  578. type
  579. pword = ^word;
  580. var
  581. p : pword;
  582. count : sw_word;
  583. begin
  584. p:=keymap;
  585. count:=p^;
  586. inc(p);
  587. while (count>0) do
  588. begin
  589. if (lo(p^)=lo(keycode)) and
  590. ((hi(p^)=0) or (hi(p^)=hi(keycode))) then
  591. begin
  592. inc(p);
  593. scankeymap:=p^;
  594. Exit;
  595. end;
  596. inc(p,2);
  597. dec(count);
  598. end;
  599. scankeymap:=0;
  600. end;
  601. function IsWordSeparator(C: char): boolean;
  602. begin
  603. IsWordSeparator:=C in[' ',#0,#255,':','=','''','"','.',',','/',';','$','#','(',')','<','>','^','*','+','-','?','&'];
  604. end;
  605. function IsSpace(C: char): boolean;
  606. begin
  607. IsSpace:=C in[' ',#0,#255];
  608. end;
  609. function LTrim(S: string): string;
  610. begin
  611. while (length(S)>0) and (S[1] in [#0,TAB,#32]) do
  612. Delete(S,1,1);
  613. LTrim:=S;
  614. end;
  615. { TAB are not same as spaces if UseTabs is set PM }
  616. function RTrim(S: string;cut_tabs : boolean): string;
  617. begin
  618. while (length(S)>0) and
  619. ((S[length(S)] in [#0,#32]) or
  620. ((S[Length(S)]=TAB) and cut_tabs)) do
  621. Delete(S,length(S),1);
  622. RTrim:=S;
  623. end;
  624. function Trim(S: string): string;
  625. begin
  626. Trim:=RTrim(LTrim(S),true);
  627. end;
  628. function EatIO: integer;
  629. begin
  630. EatIO:=IOResult;
  631. end;
  632. function ExistsFile(const FileName: string): boolean;
  633. var f: file;
  634. Exists: boolean;
  635. begin
  636. if FileName='' then Exists:=false else
  637. begin
  638. {$I-}
  639. Assign(f,FileName);
  640. Reset(f,1);
  641. Exists:=EatIO=0;
  642. Close(f);
  643. EatIO;
  644. {$I+}
  645. end;
  646. ExistsFile:=Exists;
  647. end;
  648. function Max(A,B: longint): longint;
  649. begin
  650. if A>B then Max:=A else Max:=B;
  651. end;
  652. function Min(A,B: longint): longint;
  653. begin
  654. if A<B then Min:=A else Min:=B;
  655. end;
  656. function StrToInt(const S: string): longint;
  657. var L: longint;
  658. C: integer;
  659. begin
  660. Val(S,L,C); if C<>0 then L:=-1;
  661. StrToInt:=L;
  662. end;
  663. function RExpand(const S: string; MinLen: byte): string;
  664. begin
  665. if length(S)<MinLen then
  666. RExpand:=S+CharStr(' ',MinLen-length(S))
  667. else
  668. RExpand:=S;
  669. end;
  670. function upper(const s : string) : string;
  671. var
  672. i : Sw_word;
  673. begin
  674. for i:=1 to length(s) do
  675. if s[i] in ['a'..'z'] then
  676. upper[i]:=char(byte(s[i])-32)
  677. else
  678. upper[i]:=s[i];
  679. upper[0]:=s[0];
  680. end;
  681. function DirAndNameOf(const Path: string): string;
  682. var D: DirStr; N: NameStr; E: ExtStr;
  683. begin
  684. FSplit(Path,D,N,E);
  685. DirAndNameOf:=D+N;
  686. end;
  687. type TPosOfs = {$ifdef TP}longint{$endif}{$ifdef FPC}comp{$endif};
  688. function PosToOfs(const X,Y: sw_integer): TPosOfs;
  689. type TPosRec = record LoI, HiI: sw_integer; end;
  690. var C: TPosRec;
  691. begin
  692. C.LoI:=X; C.HiI:=Y;
  693. PosToOfs:=TPosOfs(C);
  694. end;
  695. function PosToOfsP(const P: TPoint): TPosOfs;
  696. begin
  697. PosToOfsP:=PosToOfs(P.X,P.Y);
  698. end;
  699. function PointOfs(P: TPoint): TPosOfs;
  700. begin
  701. PointOfs:={longint(P.Y)*MaxLineLength+P.X}PosToOfsP(P);
  702. end;
  703. {$ifndef Undo}
  704. function NewEditorAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string): PEditorAction;
  705. var P: PEditorAction;
  706. begin
  707. New(P); FillChar(P^,SizeOf(P^),0);
  708. with P^ do
  709. begin
  710. Action:=AAction;
  711. StartPos:=AStartPos; EndPos:=AEndPos;
  712. Text:=NewStr(AText);
  713. end;
  714. NewEditorAction:=P;
  715. end;
  716. procedure DisposeEditorAction(P: PEditorAction);
  717. begin
  718. if P<>nil then
  719. begin
  720. if P^.Text<>nil then DisposeStr(P^.Text); P^.Text:=nil;
  721. Dispose(P);
  722. end;
  723. end;
  724. {$endif ndef Undo}
  725. function ExtractTabs(S: string; TabSize: Sw_integer): string;
  726. var
  727. P,PAdd: Sw_Word;
  728. begin
  729. p:=0;
  730. while p<length(s) do
  731. begin
  732. inc(p);
  733. if s[p]=TAB then
  734. begin
  735. PAdd:=TabSize-((p-1) mod TabSize);
  736. s:=copy(S,1,P-1)+CharStr(' ',PAdd)+copy(S,P+1,255);
  737. inc(P,PAdd-1);
  738. end;
  739. end;
  740. ExtractTabs:=S;
  741. end;
  742. function CompressUsingTabs(S: string; TabSize: byte): string;
  743. var TabS: string;
  744. P: byte;
  745. begin
  746. TabS:=CharStr(' ',TabSize);
  747. repeat
  748. P:=Pos(TabS,S);
  749. if P>0 then
  750. S:=copy(S,1,P-1)+TAB+copy(S,P+TabSize,255);
  751. until P=0;
  752. CompressUsingTabs:=S;
  753. end;
  754. {*****************************************************************************
  755. Forward/Backward Scanning
  756. *****************************************************************************}
  757. Const
  758. {$ifndef FPC}
  759. MaxBufLength = $7f00;
  760. NotFoundValue = -1;
  761. {$else}
  762. MaxBufLength = $7fffff00;
  763. NotFoundValue = -1;
  764. {$endif}
  765. Type
  766. Btable = Array[0..255] of Byte;
  767. Procedure BMFMakeTable(const s:string; Var t : Btable);
  768. Var
  769. x : sw_integer;
  770. begin
  771. FillChar(t,sizeof(t),length(s));
  772. For x := length(s) downto 1 do
  773. if (t[ord(s[x])] = length(s)) then
  774. t[ord(s[x])] := length(s) - x;
  775. end;
  776. function BMFScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
  777. Var
  778. buffer : Array[0..MaxBufLength-1] of Byte Absolute block;
  779. s2 : String;
  780. len,
  781. numb : Sw_Word;
  782. found : Boolean;
  783. begin
  784. len:=length(str);
  785. if len>size then
  786. begin
  787. BMFScan := NotFoundValue;
  788. exit;
  789. end;
  790. s2[0]:=chr(len); { sets the length to that of the search String }
  791. found:=False;
  792. numb:=pred(len);
  793. While (not found) and (numb<size) do
  794. begin
  795. { partial match }
  796. if buffer[numb] = ord(str[len]) then
  797. begin
  798. { less partial! }
  799. if buffer[numb-pred(len)] = ord(str[1]) then
  800. begin
  801. move(buffer[numb-pred(len)],s2[1],len);
  802. if (str=s2) then
  803. begin
  804. found:=true;
  805. break;
  806. end;
  807. end;
  808. inc(numb);
  809. end
  810. else
  811. inc(numb,Bt[buffer[numb]]);
  812. end;
  813. if not found then
  814. BMFScan := NotFoundValue
  815. else
  816. BMFScan := numb - pred(len);
  817. end;
  818. function BMFIScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
  819. Var
  820. buffer : Array[0..MaxBufLength-1] of Char Absolute block;
  821. len,
  822. numb,
  823. x : Sw_Word;
  824. found : Boolean;
  825. p : pchar;
  826. c : char;
  827. begin
  828. len:=length(str);
  829. if (len=0) or (len>size) then
  830. begin
  831. BMFIScan := NotFoundValue;
  832. exit;
  833. end;
  834. found:=False;
  835. numb:=pred(len);
  836. While (not found) and (numb<size) do
  837. begin
  838. { partial match }
  839. c:=buffer[numb];
  840. if c in ['a'..'z'] then
  841. c:=chr(ord(c)-32);
  842. if (c=str[len]) then
  843. begin
  844. { less partial! }
  845. p:=@buffer[numb-pred(len)];
  846. x:=1;
  847. while (x<=len) do
  848. begin
  849. if not(((p^ in ['a'..'z']) and (chr(ord(p^)-32)=str[x])) or
  850. (p^=str[x])) then
  851. break;
  852. inc(p);
  853. inc(x);
  854. end;
  855. if (x>len) then
  856. begin
  857. found:=true;
  858. break;
  859. end;
  860. inc(numb);
  861. end
  862. else
  863. inc(numb,Bt[ord(c)]);
  864. end;
  865. if not found then
  866. BMFIScan := NotFoundValue
  867. else
  868. BMFIScan := numb - pred(len);
  869. end;
  870. Procedure BMBMakeTable(const s:string; Var t : Btable);
  871. Var
  872. x : sw_integer;
  873. begin
  874. FillChar(t,sizeof(t),length(s));
  875. For x := 1 to length(s)do
  876. if (t[ord(s[x])] = length(s)) then
  877. t[ord(s[x])] := x-1;
  878. end;
  879. function BMBScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
  880. Var
  881. buffer : Array[0..MaxBufLength-1] of Byte Absolute block;
  882. s2 : String;
  883. len,
  884. numb : Sw_integer;
  885. found : Boolean;
  886. begin
  887. len:=length(str);
  888. if len>size then
  889. begin
  890. BMBScan := NotFoundValue;
  891. exit;
  892. end;
  893. s2[0]:=chr(len); { sets the length to that of the search String }
  894. found:=False;
  895. numb:=size-pred(len);
  896. While (not found) and (numb>0) do
  897. begin
  898. { partial match }
  899. if buffer[numb] = ord(str[1]) then
  900. begin
  901. { less partial! }
  902. if buffer[numb+pred(len)] = ord(str[len]) then
  903. begin
  904. move(buffer[numb],s2[1],len);
  905. if (str=s2) then
  906. begin
  907. found:=true;
  908. break;
  909. end;
  910. end;
  911. dec(numb);
  912. end
  913. else
  914. dec(numb,Bt[buffer[numb]]);
  915. end;
  916. if not found then
  917. BMBScan := NotFoundValue
  918. else
  919. BMBScan := numb;
  920. end;
  921. function BMBIScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
  922. Var
  923. buffer : Array[0..MaxBufLength-1] of Char Absolute block;
  924. len,
  925. numb,
  926. x : Sw_integer;
  927. found : Boolean;
  928. p : pchar;
  929. c : char;
  930. begin
  931. len:=length(str);
  932. if (len=0) or (len>size) then
  933. begin
  934. BMBIScan := NotFoundValue;
  935. exit;
  936. end;
  937. found:=False;
  938. numb:=size-len;
  939. While (not found) and (numb>0) do
  940. begin
  941. { partial match }
  942. c:=buffer[numb];
  943. if c in ['a'..'z'] then
  944. c:=chr(ord(c)-32);
  945. if (c=str[1]) then
  946. begin
  947. { less partial! }
  948. p:=@buffer[numb];
  949. x:=1;
  950. while (x<=len) do
  951. begin
  952. if not(((p^ in ['a'..'z']) and (chr(ord(p^)-32)=str[x])) or
  953. (p^=str[x])) then
  954. break;
  955. inc(p);
  956. inc(x);
  957. end;
  958. if (x>len) then
  959. begin
  960. found:=true;
  961. break;
  962. end;
  963. dec(numb);
  964. end
  965. else
  966. dec(numb,Bt[ord(c)]);
  967. end;
  968. if not found then
  969. BMBIScan := NotFoundValue
  970. else
  971. BMBIScan := numb;
  972. end;
  973. {*****************************************************************************
  974. PLine,TLineCollection
  975. *****************************************************************************}
  976. function NewLine(S: string): PLine;
  977. var P: PLine;
  978. begin
  979. New(P); FillChar(P^,SizeOf(P^),0);
  980. P^.Text:=NewStr(S);
  981. NewLine:=P;
  982. end;
  983. procedure DisposeLine(P: PLine);
  984. begin
  985. if P<>nil then
  986. begin
  987. if P^.Text<>nil then DisposeStr(P^.Text);
  988. if P^.Format<>nil then DisposeStr(P^.Format);
  989. Dispose(P);
  990. end;
  991. end;
  992. function TLineCollection.At(Index: sw_Integer): PLine;
  993. begin
  994. At:=inherited At(Index);
  995. end;
  996. procedure TLineCollection.FreeItem(Item: Pointer);
  997. begin
  998. if Item<>nil then DisposeLine(Item);
  999. end;
  1000. constructor TIndicator.Init(var Bounds: TRect);
  1001. begin
  1002. inherited Init(Bounds);
  1003. GrowMode := gfGrowLoY + gfGrowHiY;
  1004. end;
  1005. procedure TIndicator.Draw;
  1006. var
  1007. Color: Byte;
  1008. Frame: Char;
  1009. L: array[0..1] of Longint;
  1010. S: String[15];
  1011. B: TDrawBuffer;
  1012. begin
  1013. if (State and sfDragging = 0) and (State and sfActive <> 0) then
  1014. begin
  1015. Color := GetColor(1);
  1016. Frame := #205;
  1017. end
  1018. else
  1019. begin
  1020. if (State and sfDragging)<>0 then
  1021. Color := GetColor(2)
  1022. else
  1023. Color := GetColor(3);
  1024. Frame := #196;
  1025. end;
  1026. MoveChar(B, Frame, Color, Size.X);
  1027. if State and sfActive<>0 then
  1028. begin
  1029. if Modified then
  1030. WordRec (B[0]).Lo := ord('*');
  1031. {$ifdef debug}
  1032. if StoreUndo then
  1033. WordRec (B[1]).Lo := ord('S');
  1034. if SyntaxComplete then
  1035. WordRec(B[2]).lo := ord('C');
  1036. if UseTabs then
  1037. WordRec(B[3]).lo := ord('T');
  1038. {$endif debug}
  1039. L[0] := Location.Y + 1;
  1040. L[1] := Location.X + 1;
  1041. FormatStr(S, '%d:%d ', L);
  1042. MoveStr(B[8 - Pos(':', S)], S, Color);
  1043. end;
  1044. WriteBuf(0, 0, Size.X, 1, B);
  1045. end;
  1046. function TIndicator.GetPalette: PPalette;
  1047. const
  1048. P: string[Length(CIndicator)] = CIndicator;
  1049. begin
  1050. GetPalette := @P;
  1051. end;
  1052. procedure TIndicator.SetState(AState: Word; Enable: Boolean);
  1053. begin
  1054. inherited SetState(AState, Enable);
  1055. if (AState = sfDragging) or (AState=sfActive) then
  1056. DrawView;
  1057. end;
  1058. procedure TIndicator.SetValue(ALocation: TPoint; AModified: Boolean);
  1059. begin
  1060. if (Location.X<>ALocation.X) or
  1061. (Location.Y<>ALocation.Y) or
  1062. (Modified <> AModified) then
  1063. begin
  1064. Location := ALocation;
  1065. Modified := AModified;
  1066. DrawView;
  1067. end;
  1068. end;
  1069. constructor TIndicator.Load(var S: TStream);
  1070. begin
  1071. inherited Load(S);
  1072. S.Read(Location,SizeOf(Location));
  1073. S.Read(Modified,SizeOf(Modified));
  1074. end;
  1075. procedure TIndicator.Store(var S: TStream);
  1076. begin
  1077. inherited Store(S);
  1078. S.Write(Location,SizeOf(Location));
  1079. S.Write(Modified,SizeOf(Modified));
  1080. end;
  1081. {*****************************************************************************
  1082. TCodeEditor
  1083. *****************************************************************************}
  1084. constructor TCodeEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  1085. PScrollBar; AIndicator: PIndicator; ABufSize:Sw_Word);
  1086. begin
  1087. inherited Init(Bounds,AHScrollBar,AVScrollBar);
  1088. {$ifndef Undo}
  1089. StoreUndo:=false;
  1090. {$else Undo}
  1091. StoreUndo:=true;
  1092. {$endif def Undo}
  1093. new(UndoList,init(500,1000));
  1094. new(RedoList,init(500,1000));
  1095. New(Lines, Init(500,1000));
  1096. { we have always need at least 1 line }
  1097. Lines^.Insert(NewLine(''));
  1098. { ^^^ why? setlinetext() inserts automatically if neccessary and
  1099. getlinetext() checks whether you're in range...
  1100. because otherwise you search for line with index -1 (PM)
  1101. Then I think the algorithm should be changed to handle this special case,
  1102. instead of applying this "work-around" - Gabor
  1103. }
  1104. SetState(sfCursorVis,true);
  1105. SetFlags(DefaultCodeEditorFlags); TabSize:=DefaultTabSize;
  1106. SetHighlightRow(-1);
  1107. SetDebuggerRow(-1);
  1108. SetCurPtr(0,0);
  1109. Indicator:=AIndicator;
  1110. {$ifdef TEST_PARTIAL_SYNTAX}
  1111. SyntaxComplete:=true;
  1112. {$endif TEST_PARTIAL_SYNTAX}
  1113. UpdateIndicator;
  1114. LimitsChanged;
  1115. end;
  1116. procedure TCodeEditor.SetFlags(AFlags: longint);
  1117. var I: sw_integer;
  1118. OldFlags: longint;
  1119. begin
  1120. OldFlags:=Flags;
  1121. Flags:=AFlags;
  1122. if ((OldFlags xor Flags) and efCodeComplete)<>0 then
  1123. ClearCodeCompleteWord;
  1124. SetInsertMode((Flags and efInsertMode)<>0);
  1125. if (Flags and efSyntaxHighlight)<>0 then
  1126. UpdateAttrs(0,attrAll) else
  1127. for I:=0 to GetLineCount-1 do
  1128. SetLineFormat(I,'');
  1129. UpdateIndicator;
  1130. DrawView;
  1131. end;
  1132. function TCodeEditor.GetErrorMessage: string;
  1133. var S: string;
  1134. begin
  1135. if ErrorMessage=nil then S:='' else S:=ErrorMessage^;
  1136. GetErrorMessage:=S;
  1137. end;
  1138. procedure TCodeEditor.SetErrorMessage(const S: string);
  1139. begin
  1140. if ErrorMessage<>nil then DisposeStr(ErrorMessage);
  1141. ErrorMessage:=NewStr(S);
  1142. DrawView;
  1143. end;
  1144. procedure TCodeEditor.Lock;
  1145. begin
  1146. Inc(LockFlag);
  1147. end;
  1148. procedure TCodeEditor.UnLock;
  1149. begin
  1150. {$ifdef DEBUG}
  1151. if lockflag=0 then
  1152. Bug('negative lockflag',nil)
  1153. else
  1154. {$endif DEBUG}
  1155. Dec(LockFlag);
  1156. if (LockFlag>0) then
  1157. exit;
  1158. if DrawCalled then
  1159. DrawView;
  1160. If IndicatorDrawCalled and
  1161. assigned(Indicator) then
  1162. begin
  1163. Indicator^.DrawView;
  1164. IndicatorDrawCalled:=false;
  1165. end;
  1166. If DrawCursorCalled then
  1167. Begin
  1168. DrawCursor;
  1169. DrawCursorCalled:=false;
  1170. End;
  1171. end;
  1172. procedure TCodeEditor.AdjustSelectionPos(CurPosX, CurPosY: sw_integer; DeltaX, DeltaY: sw_integer);
  1173. var CP: TPoint;
  1174. begin
  1175. if ValidBlock=false then Exit;
  1176. CP.X:=CurPosX; CP.Y:=CurPosY;
  1177. if (PosToOfsP(SelStart)<=PosToOfsP(CP)) and (PosToOfsP(CP)<PosToOfsP(SelEnd)) then
  1178. begin
  1179. { CurPos is IN selection }
  1180. Inc(SelEnd.Y,DeltaY);
  1181. if (CP.Y=SelEnd.Y) and
  1182. ((SelStart.Y<>SelEnd.Y) or (SelStart.X<=CP.X)) and
  1183. (CP.X<=SelEnd.X) then
  1184. Inc(SelEnd.X,DeltaX);
  1185. SelectionChanged;
  1186. end
  1187. else
  1188. if (PosToOfsP(CP)<=PosToOfsP(SelStart)) then
  1189. begin
  1190. { CurPos is BEFORE selection }
  1191. if (CP.Y=SelStart.Y) and (CP.Y=SelEnd.Y) and (DeltaY<0) then
  1192. begin
  1193. SelStart:=CurPos; SelEnd:=CurPos;
  1194. end
  1195. else
  1196. if (CP.Y=SelStart.Y) then
  1197. begin
  1198. if CP.X<SelStart.X then
  1199. Inc(SelStart.X,DeltaX);
  1200. end;
  1201. { else}
  1202. begin
  1203. Inc(SelStart.Y,DeltaY);
  1204. Inc(SelEnd.Y,DeltaY);
  1205. end;
  1206. if SelEnd.Y=CurPos.Y then Inc(SelEnd.X,DeltaX);
  1207. SelectionChanged;
  1208. end
  1209. else
  1210. begin
  1211. { CurPos is AFTER selection }
  1212. { actually we don't have to do anything here }
  1213. end;
  1214. end;
  1215. procedure TCodeEditor.AdjustSelection(DeltaX, DeltaY: sw_integer);
  1216. begin
  1217. AdjustSelectionPos(CurPos.X,CurPos.Y,DeltaX,DeltaY);
  1218. end;
  1219. procedure TCodeEditor.TrackCursor(Center: boolean);
  1220. var D: TPoint;
  1221. begin
  1222. D:=Delta;
  1223. if CurPos.Y<Delta.Y then D.Y:=CurPos.Y else
  1224. if CurPos.Y>Delta.Y+Size.Y-1 then D.Y:=CurPos.Y-Size.Y+1;
  1225. if CurPos.X<Delta.X then D.X:=CurPos.X else
  1226. if CurPos.X>Delta.X+Size.X-1 then D.X:=CurPos.X-Size.X+1;
  1227. if {((Delta.X<>D.X) or (Delta.Y<>D.Y)) and }Center then
  1228. begin
  1229. { loose centering for debugger PM }
  1230. while (CurPos.Y-D.Y)<(Size.Y div 3) do Dec(D.Y);
  1231. while (CurPos.Y-D.Y)>2*(Size.Y div 3) do Inc(D.Y);
  1232. end;
  1233. if (Delta.X<>D.X) or (Delta.Y<>D.Y) then
  1234. ScrollTo(D.X,D.Y);
  1235. DrawCursor;
  1236. UpdateIndicator;
  1237. end;
  1238. procedure TCodeEditor.ScrollTo(X, Y: sw_Integer);
  1239. begin
  1240. inherited ScrollTo(X,Y);
  1241. if (HScrollBar=nil) or (VScrollBar=nil) then
  1242. begin Delta.X:=X; Delta.Y:=Y; end;
  1243. DrawView;
  1244. end;
  1245. procedure TCodeEditor.UpdateIndicator;
  1246. begin
  1247. if Indicator<>nil then
  1248. begin
  1249. Indicator^.Location:=CurPos;
  1250. Indicator^.Modified:=Modified;
  1251. {$ifdef debug}
  1252. Indicator^.StoreUndo:=StoreUndo;
  1253. {$ifdef TEST_PARTIAL_SYNTAX}
  1254. Indicator^.SyntaxComplete:=SyntaxComplete and ((Flags and efSyntaxHighlight)<>0);
  1255. {$endif TEST_PARTIAL_SYNTAX}
  1256. Indicator^.UseTabs:=((Flags and efUseTabCharacters)<>0);
  1257. {$endif debug}
  1258. if lockflag>0 then
  1259. IndicatorDrawCalled:=true
  1260. else
  1261. Indicator^.DrawView;
  1262. end;
  1263. end;
  1264. procedure TCodeEditor.LimitsChanged;
  1265. begin
  1266. SetLimit(MaxLineLength+1,GetLineCount);
  1267. end;
  1268. procedure TCodeEditor.ConvertEvent(var Event: TEvent);
  1269. var
  1270. Key: Word;
  1271. begin
  1272. if Event.What = evKeyDown then
  1273. begin
  1274. if (Event.KeyShift and kbShift <> 0) and
  1275. (Event.ScanCode >= $47) and (Event.ScanCode <= $51) then
  1276. Event.CharCode := #0;
  1277. Key := Event.KeyCode;
  1278. if KeyState <> 0 then
  1279. begin
  1280. if (Lo(Key) >= $01) and (Lo(Key) <= $1A) then Inc(Key, $40);
  1281. if (Lo(Key) >= $61) and (Lo(Key) <= $7A) then Dec(Key, $20);
  1282. end;
  1283. Key := ScanKeyMap(KeyMap[KeyState], Key);
  1284. if (KeyState<>0) and (Key=0) then
  1285. ClearEvent(Event); { eat second key if unrecognized after ^Q or ^K }
  1286. KeyState := 0;
  1287. if Key <> 0 then
  1288. if Hi(Key) = $FF then
  1289. begin
  1290. KeyState := Lo(Key);
  1291. ClearEvent(Event);
  1292. end
  1293. else
  1294. begin
  1295. Event.What := evCommand;
  1296. Event.Command := Key;
  1297. end;
  1298. end;
  1299. end;
  1300. procedure TCodeEditor.HandleEvent(var Event: TEvent);
  1301. var DontClear : boolean;
  1302. procedure CheckScrollBar(P: PScrollBar; var D: Sw_Integer);
  1303. begin
  1304. if (Event.InfoPtr = P) and (P^.Value <> D) then
  1305. begin
  1306. D := P^.Value;
  1307. DrawView;
  1308. end;
  1309. end;
  1310. procedure GetMousePos(var P: TPoint);
  1311. begin
  1312. MakeLocal(Event.Where,P);
  1313. Inc(P.X,Delta.X); Inc(P.Y,Delta.Y);
  1314. end;
  1315. type TCCAction = (ccCheck,ccClear,ccDontCare);
  1316. var
  1317. StartP,P: TPoint;
  1318. E: TEvent;
  1319. OldEvent : PEvent;
  1320. CCAction: TCCAction;
  1321. begin
  1322. CCAction:=ccClear;
  1323. E:=Event;
  1324. OldEvent:=CurEvent;
  1325. if (E.What and (evMouse or evKeyboard))<>0 then
  1326. CurEvent:=@E;
  1327. if (InASCIIMode=false) or (Event.What<>evKeyDown) then
  1328. if (Event.What<>evKeyDown) or
  1329. ((Event.KeyCode<>kbEnter) and (Event.KeyCode<>kbEsc)) or
  1330. (CompleteState<>csOffering) then
  1331. ConvertEvent(Event);
  1332. case Event.What of
  1333. evMouseDown :
  1334. if MouseInView(Event.Where) then
  1335. if (Event.Buttons=mbRightButton) then
  1336. begin
  1337. MakeLocal(Event.Where,P); Inc(P.X); Inc(P.Y);
  1338. LocalMenu(P);
  1339. ClearEvent(Event);
  1340. end else
  1341. if Event.Buttons=mbLeftButton then
  1342. begin
  1343. GetMousePos(P);
  1344. StartP:=P;
  1345. SetCurPtr(P.X,P.Y);
  1346. repeat
  1347. GetMousePos(P);
  1348. if PointOfs(P)<PointOfs(StartP)
  1349. then SetSelection(P,StartP)
  1350. else SetSelection(StartP,P);
  1351. SetCurPtr(P.X,P.Y);
  1352. DrawView;
  1353. until not MouseEvent(Event, evMouseMove+evMouseAuto);
  1354. DrawView;
  1355. end;
  1356. evKeyDown :
  1357. begin
  1358. { Scancode is almost never zero PM }
  1359. { this is supposed to enable entering of ASCII chars below 32,
  1360. which are normally interpreted as control chars. So, when you enter
  1361. Alt+24 (on the numeric pad) then this will normally move the cursor
  1362. one line down, but if you do it in ASCII mode (also after Ctrl+B)
  1363. then this will insert the ASCII #24 char (upper arrow) in the
  1364. source code. - Gabor }
  1365. if InASCIIMode {and (Event.CharCode<>0)} then
  1366. begin
  1367. AddChar(Event.CharCode);
  1368. if (CompleteState<>csDenied) or (Event.CharCode=#32) then
  1369. CCAction:=ccCheck
  1370. else
  1371. CCAction:=ccClear;
  1372. end
  1373. else
  1374. begin
  1375. DontClear:=false;
  1376. case Event.KeyCode of
  1377. kbAltF10 :
  1378. Message(@Self,evCommand,cmLocalMenu,@Self);
  1379. kbEnter :
  1380. if CompleteState=csOffering then
  1381. CodeCompleteApply
  1382. else
  1383. Message(@Self,evCommand,cmNewLine,nil);
  1384. kbEsc :
  1385. if CompleteState=csOffering then
  1386. CodeCompleteCancel;
  1387. else
  1388. case Event.CharCode of
  1389. #9,#32..#255 :
  1390. begin
  1391. NoSelect:=true;
  1392. AddChar(Event.CharCode);
  1393. NoSelect:=false;
  1394. if (CompleteState<>csDenied) or (Event.CharCode=#32) then
  1395. CCAction:=ccCheck
  1396. else
  1397. CCAction:=ccClear;
  1398. end;
  1399. else
  1400. DontClear:=true;
  1401. end; { case Event.CharCode .. }
  1402. end; { case Event.KeyCode .. }
  1403. if not DontClear then
  1404. ClearEvent(Event);
  1405. end;
  1406. InASCIIMode:=false;
  1407. end;
  1408. evCommand :
  1409. begin
  1410. DontClear:=false;
  1411. case Event.Command of
  1412. cmASCIIChar : InASCIIMode:=not InASCIIMode;
  1413. cmAddChar : AddChar(chr(longint(Event.InfoPtr)));
  1414. cmCharLeft : CharLeft;
  1415. cmCharRight : CharRight;
  1416. cmWordLeft : WordLeft;
  1417. cmWordRight : WordRight;
  1418. cmLineStart : LineStart;
  1419. cmLineEnd : LineEnd;
  1420. cmLineUp : LineUp;
  1421. cmLineDown : LineDown;
  1422. cmPageUp : PageUp;
  1423. cmPageDown : PageDown;
  1424. cmTextStart : TextStart;
  1425. cmTextEnd : TextEnd;
  1426. cmNewLine : InsertLine;
  1427. cmBreakLine : BreakLine;
  1428. cmBackSpace : BackSpace;
  1429. cmDelChar : DelChar;
  1430. cmDelWord : DelWord;
  1431. cmDelStart : DelStart;
  1432. cmDelEnd : DelEnd;
  1433. cmDelLine : DelLine;
  1434. cmInsMode : InsMode;
  1435. cmStartSelect : StartSelect;
  1436. cmHideSelect : HideSelect;
  1437. cmUpdateTitle : ;
  1438. cmEndSelect : EndSelect;
  1439. cmDelSelect : DelSelect;
  1440. cmCopyBlock : CopyBlock;
  1441. cmMoveBlock : MoveBlock;
  1442. cmIndentBlock : IndentBlock;
  1443. cmUnindentBlock : UnindentBlock;
  1444. cmSelStart : JumpSelStart;
  1445. cmSelEnd : JumpSelEnd;
  1446. cmLastCursorPos : JumpToLastCursorPos;
  1447. cmJumpMark0..cmJumpMark9 : JumpMark(Event.Command-cmJumpMark0);
  1448. cmSetMark0..cmSetMark9 : DefineMark(Event.Command-cmSetMark0);
  1449. cmSelectWord : SelectWord;
  1450. cmSelectLine : SelectLine;
  1451. cmWriteBlock : WriteBlock;
  1452. cmReadBlock : ReadBlock;
  1453. cmPrintBlock : PrintBlock;
  1454. { ------ }
  1455. cmFind : Find;
  1456. cmReplace : Replace;
  1457. cmSearchAgain : DoSearchReplace;
  1458. cmJumpLine : GotoLine;
  1459. { ------ }
  1460. cmCut : ClipCut;
  1461. cmCopy : ClipCopy;
  1462. cmPaste : ClipPaste;
  1463. {$ifdef WinClipSupported}
  1464. cmCopyWin : ClipCopyWin;
  1465. cmPasteWin : ClipPasteWin;
  1466. {$endif WinClipSupported}
  1467. cmUndo : Undo;
  1468. cmRedo : Redo;
  1469. cmClear : DelSelect;
  1470. cmExpandCodeTemplate: ExpandCodeTemplate;
  1471. cmLocalMenu :
  1472. begin
  1473. P:=CurPos; Inc(P.X); Inc(P.Y);
  1474. LocalMenu(P);
  1475. end;
  1476. else
  1477. begin
  1478. DontClear:=true;
  1479. CCAction:=ccDontCare;
  1480. end;
  1481. end;
  1482. if DontClear=false then
  1483. ClearEvent(Event);
  1484. end;
  1485. {$ifdef TEST_PARTIAL_SYNTAX}
  1486. evIdle :
  1487. begin
  1488. { Complete syntax by 20 lines increment }
  1489. { could already be quite lengthy on slow systems }
  1490. if not SyntaxComplete then
  1491. UpdateAttrsRange(LastSyntaxedLine,LastSyntaxedLine+20,AttrAll);
  1492. end;
  1493. {$endif TEST_PARTIAL_SYNTAX}
  1494. evBroadcast :
  1495. begin
  1496. CCAction:=ccDontCare;
  1497. case Event.Command of
  1498. cmUpdate :
  1499. Update;
  1500. cmClearLineHighlights :
  1501. SetHighlightRow(-1);
  1502. cmResetDebuggerRow :
  1503. SetDebuggerRow(-1);
  1504. cmScrollBarChanged:
  1505. if (Event.InfoPtr = HScrollBar) or
  1506. (Event.InfoPtr = VScrollBar) then
  1507. begin
  1508. CheckScrollBar(HScrollBar, Delta.X);
  1509. CheckScrollBar(VScrollBar, Delta.Y);
  1510. end;
  1511. end;
  1512. end;
  1513. else CCAction:=ccDontCare;
  1514. end;
  1515. inherited HandleEvent(Event);
  1516. CurEvent:=OldEvent;
  1517. case CCAction of
  1518. ccCheck : CodeCompleteCheck;
  1519. ccClear : ClearCodeCompleteWord;
  1520. end;
  1521. end;
  1522. procedure TCodeEditor.UpdateUndoRedo(cm : word; action : byte);
  1523. var UndoMenu : PMenuItem;
  1524. begin
  1525. UndoMenu:=PAdvancedMenuBar(MenuBar)^.GetMenuItem(cm);
  1526. if assigned(UndoMenu) then
  1527. begin
  1528. If assigned(UndoMenu^.Param) then
  1529. DisposeStr(UndoMenu^.Param);
  1530. if action<lastaction then
  1531. UndoMenu^.Param:=NewStr(ActionString[action]);
  1532. end;
  1533. end;
  1534. procedure TCodeEditor.Update;
  1535. begin
  1536. LimitsChanged;
  1537. SelectionChanged; HighlightChanged;
  1538. UpdateIndicator;
  1539. DrawView;
  1540. end;
  1541. function TCodeEditor.GetLocalMenu: PMenu;
  1542. begin
  1543. GetLocalMenu:=nil;
  1544. end;
  1545. function TCodeEditor.GetCommandTarget: PView;
  1546. begin
  1547. GetCommandTarget:=@Self;
  1548. end;
  1549. function TCodeEditor.CreateLocalMenuView(var Bounds: TRect; M: PMenu): PMenuPopup;
  1550. var MV: PMenuPopup;
  1551. begin
  1552. New(MV, Init(Bounds, M));
  1553. CreateLocalMenuView:=MV;
  1554. end;
  1555. procedure TCodeEditor.LocalMenu(P: TPoint);
  1556. var M: PMenu;
  1557. MV: PMenuPopUp;
  1558. R: TRect;
  1559. Re: word;
  1560. begin
  1561. M:=GetLocalMenu;
  1562. if M=nil then Exit;
  1563. if LastLocalCmd<>0 then
  1564. M^.Default:=SearchMenuItem(M,LastLocalCmd);
  1565. Desktop^.GetExtent(R);
  1566. MakeGlobal(P,R.A); {Desktop^.MakeLocal(R.A,R.A);}
  1567. MV:=CreateLocalMenuView(R,M);
  1568. Re:=Application^.ExecView(MV);
  1569. if M^.Default=nil then LastLocalCmd:=0
  1570. else LastLocalCmd:=M^.Default^.Command;
  1571. Dispose(MV, Done);
  1572. if Re<>0 then
  1573. Message(GetCommandTarget,evCommand,Re,@Self);
  1574. end;
  1575. procedure TCodeEditor.Draw;
  1576. var SelectColor,
  1577. HighlightColColor,
  1578. HighlightRowColor,
  1579. ErrorMessageColor : word;
  1580. B: TDrawBuffer;
  1581. X,Y,AX,AY,MaxX: sw_integer;
  1582. PX: TPoint;
  1583. LineCount: sw_integer;
  1584. Line: PLine;
  1585. LineText,Format: string;
  1586. isBreak : boolean;
  1587. C: char;
  1588. FreeFormat: array[0..255] of boolean;
  1589. Color: word;
  1590. ColorTab: array[coFirstColor..coLastColor] of word;
  1591. ErrorLine: integer;
  1592. ErrorMsg: string[MaxViewWidth];
  1593. function CombineColors(Orig,Modifier: byte): byte;
  1594. var Color: byte;
  1595. begin
  1596. if (Modifier and $0f)=0 then
  1597. Color:=(Orig and $0f) or (Modifier and $f0)
  1598. else
  1599. Color:=(Orig and $f0) or (Modifier and $0f);
  1600. { do not allow invisible }
  1601. { use white as foreground in this case }
  1602. if (Color and $f) = ((Color div $10) and $7) then
  1603. Color:=(Color and $F0) or $F;
  1604. CombineColors:=Color;
  1605. end;
  1606. const NulLine : TLine = (Text: nil; Format: nil);
  1607. begin
  1608. if LockFlag>0 then
  1609. begin
  1610. DrawCalled:=true;
  1611. Exit;
  1612. end;
  1613. DrawCalled:=false;
  1614. ErrorMsg:=copy(GetErrorMessage,1,MaxViewWidth);
  1615. if ErrorMsg='' then ErrorLine:=-1 else
  1616. if (CurPos.Y-Delta.Y)<(Size.Y div 2) then ErrorLine:=Size.Y-1
  1617. else ErrorLine:=0;
  1618. LineCount:=GetLineCount;
  1619. ColorTab[coTextColor]:=GetColor(1);
  1620. ColorTab[coWhiteSpaceColor]:=GetColor(2);
  1621. ColorTab[coCommentColor]:=GetColor(3);
  1622. ColorTab[coReservedWordColor]:=GetColor(4);
  1623. ColorTab[coIdentifierColor]:=GetColor(5);
  1624. ColorTab[coStringColor]:=GetColor(6);
  1625. ColorTab[coNumberColor]:=GetColor(7);
  1626. ColorTab[coAssemblerColor]:=GetColor(8);
  1627. ColorTab[coSymbolColor]:=GetColor(9);
  1628. ColorTab[coDirectiveColor]:=GetColor(13);
  1629. ColorTab[coHexNumberColor]:=GetColor(14);
  1630. ColorTab[coTabColor]:=GetColor(15);
  1631. { break same as error }
  1632. ColorTab[coBreakColor]:=GetColor(16);
  1633. SelectColor:=GetColor(10);
  1634. HighlightColColor:=GetColor(11);
  1635. HighlightRowColor:=GetColor(12);
  1636. ErrorMessageColor:=GetColor(16);
  1637. {$ifdef TEST_PARTIAL_SYNTAX}
  1638. If LastSyntaxedLine<Delta.Y+Size.Y then
  1639. UpdateAttrsRange(LastSyntaxedLine,Delta.Y+Size.Y,AttrAll);
  1640. {$endif TEST_PARTIAL_SYNTAX}
  1641. for Y:=0 to Size.Y-1 do
  1642. if Y=ErrorLine then
  1643. begin
  1644. MoveChar(B,' ',ErrorMessageColor,Size.X);
  1645. MoveStr(B,ErrorMsg,ErrorMessageColor);
  1646. WriteLine(0,Y,Size.X,1,B);
  1647. end else
  1648. begin
  1649. AY:=Delta.Y+Y;
  1650. Color:=ColorTab[coTextColor];
  1651. FillChar(FreeFormat,SizeOf(FreeFormat),1);
  1652. MoveChar(B,' ',Color,Size.X);
  1653. if AY<LineCount then
  1654. begin
  1655. Line:=GetLine(AY);
  1656. IsBreak:=Lines^.at(AY)^.isBreakpoint;
  1657. end
  1658. else
  1659. begin
  1660. Line:=@NulLine;
  1661. IsBreak:=false;
  1662. end;
  1663. GetDisplayTextFormat(AY,LineText,Format);
  1664. { if (Flags and efSyntaxHighlight)<>0 then MaxX:=length(LineText)+1
  1665. else }MaxX:=Size.X+Delta.X;
  1666. for X:=1 to Min(MaxX,255) do
  1667. begin
  1668. AX:=Delta.X+X-1;
  1669. if X<=length(LineText) then C:=LineText[X] else C:=' ';
  1670. PX.X:=AX-Delta.X; PX.Y:=AY;
  1671. if (Highlight.A.X<>Highlight.B.X) or (Highlight.A.Y<>Highlight.B.Y) then
  1672. begin
  1673. if (PointOfs(Highlight.A)<=PointOfs(PX)) and (PointOfs(PX)<PointOfs(Highlight.B)) then
  1674. begin
  1675. Color:=SelectColor;
  1676. FreeFormat[X]:=false;
  1677. end;
  1678. end else
  1679. { no highlight }
  1680. begin
  1681. if (Flags and efVerticalBlocks<>0) then
  1682. begin
  1683. if (SelStart.X<=AX) and (AX<=SelEnd.X) and
  1684. (SelStart.Y<=AY) and (AY<=SelEnd.Y) then
  1685. begin Color:=SelectColor; FreeFormat[X]:=false; end;
  1686. end else
  1687. if PointOfs(SelStart)<>PointOfs(SelEnd) then
  1688. if (PointOfs(SelStart)<=PointOfs(PX)) and (PointOfs(PX)<PointOfs(SelEnd)) then
  1689. begin Color:=SelectColor; FreeFormat[X]:=false; end;
  1690. end;
  1691. if FreeFormat[X] then
  1692. if X<=length(Format) then
  1693. {Color:=ColorTab[ord(Format[X])] else Color:=ColorTab[coTextColor];
  1694. this give BoundsCheckError with -Cr quite often PM }
  1695. Color:=ColorTab[ord(Format[X]) mod (coLastColor + 1)] else Color:=ColorTab[coTextColor];
  1696. if ( ((Flags and efHighlightRow) <>0) and
  1697. (PX.Y=CurPos.Y) ) and (HighlightRow=-1) then
  1698. begin
  1699. Color:=CombineColors(Color,HighlightRowColor);
  1700. FreeFormat[X]:=false;
  1701. end;
  1702. if ( ((Flags and efHighlightColumn)<>0) and (PX.X=CurPos.X) ) then
  1703. begin
  1704. Color:=CombineColors(Color,HighlightColColor);
  1705. FreeFormat[X]:=false;
  1706. end;
  1707. if HighlightRow=AY then
  1708. begin
  1709. Color:=CombineColors(Color,HighlightRowColor);
  1710. FreeFormat[X]:=false;
  1711. end;
  1712. if isbreak then
  1713. begin
  1714. Color:=ColorTab[coBreakColor];
  1715. FreeFormat[X]:=false;
  1716. end;
  1717. if DebuggerRow=AY then
  1718. begin
  1719. Color:=CombineColors(Color,HighlightRowColor);
  1720. FreeFormat[X]:=false;
  1721. end;
  1722. if (0<=X-1-Delta.X) and (X-1-Delta.X<MaxViewWidth) then
  1723. MoveChar(B[X-1-Delta.X],C,Color,1);
  1724. end;
  1725. WriteLine(0,Y,Size.X,1,B);
  1726. end;
  1727. DrawCursor;
  1728. end;
  1729. procedure TCodeEditor.DrawCursor;
  1730. begin
  1731. if lockflag>0 then
  1732. DrawCursorCalled:=true
  1733. else
  1734. SetCursor(CurPos.X-Delta.X,CurPos.Y-Delta.Y);
  1735. SetState(sfCursorIns,Overwrite);
  1736. end;
  1737. function TCodeEditor.Overwrite: boolean;
  1738. begin
  1739. Overwrite:=(Flags and efInsertMode)=0;
  1740. end;
  1741. function TCodeEditor.GetLineCount: sw_integer;
  1742. begin
  1743. GetLineCount:=Lines^.Count;
  1744. end;
  1745. function TCodeEditor.GetLine(I: sw_integer): PLine;
  1746. begin
  1747. GetLine:=Lines^.At(I);
  1748. end;
  1749. function TCodeEditor.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
  1750. var S: string;
  1751. CP,RX: sw_integer;
  1752. begin
  1753. S:=GetLineText(Line);
  1754. CP:=1; RX:=0;
  1755. while (CP<=length(S)) and (CP<=CharIdx) do
  1756. begin
  1757. if S[CP]=TAB then
  1758. Inc(RX,TabSize-(RX mod TabSize))
  1759. else
  1760. Inc(RX);
  1761. Inc(CP);
  1762. end;
  1763. CharIdxToLinePos:=RX-1;
  1764. end;
  1765. function TCodeEditor.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
  1766. var S: string;
  1767. CP,RX: sw_integer;
  1768. begin
  1769. S:=GetLineText(Line);
  1770. if S='' then
  1771. CP:=0
  1772. else
  1773. begin
  1774. CP:=0; RX:=0;
  1775. while (RX<=X) and (CP<=length(S)) do
  1776. begin
  1777. Inc(CP);
  1778. if S[CP]=TAB then
  1779. Inc(RX,TabSize-(RX mod TabSize))
  1780. else
  1781. Inc(RX);
  1782. end;
  1783. end;
  1784. LinePosToCharIdx:=CP;
  1785. end;
  1786. {function TCodeEditor.GetLineTextPos(Line,X: integer): integer;
  1787. var
  1788. S: string;
  1789. rx,i : Sw_integer;
  1790. begin
  1791. S:=GetLineText(Line);
  1792. i:=0; rx:=0;
  1793. while (RX<X) and (i<Length(s)) do
  1794. begin
  1795. inc(i);
  1796. inc(rx);
  1797. if s[i]=#9 then
  1798. inc(rx,TabSize-(rx mod tabsize));
  1799. end;
  1800. if RX<X then Inc(I,X-RX);
  1801. GetLineTextPos:=i;
  1802. end;
  1803. function TCodeEditor.GetDisplayTextPos(Line,X: integer): integer;
  1804. var
  1805. S: string;
  1806. L: PLine;
  1807. rx,i : Sw_integer;
  1808. begin
  1809. S:='';
  1810. if Line<Lines^.Count then
  1811. begin
  1812. L:=Lines^.At(Line);
  1813. if assigned(L^.Text) then
  1814. S:=L^.Text^;
  1815. end;
  1816. i:=0;
  1817. rx:=0;
  1818. while (i<X) and (i<Length(s)) do
  1819. begin
  1820. inc(i);
  1821. inc(rx);
  1822. if s[i]=#9 then
  1823. inc(rx,TabSize-(rx mod tabsize));
  1824. end;
  1825. GetDisplayTextPos:=rx;
  1826. end;}
  1827. function TCodeEditor.GetLineText(I: sw_integer): string;
  1828. var
  1829. L : PLine;
  1830. begin
  1831. GetLineText:='';
  1832. if I<Lines^.Count then
  1833. begin
  1834. L:=Lines^.At(I);
  1835. if assigned(L^.Text) then
  1836. GetLineText:=L^.Text^;
  1837. end;
  1838. end;
  1839. procedure TCodeEditor.SetLineText(I: sw_integer;const S: string);
  1840. var
  1841. L : PLine;
  1842. AddCount : Sw_Integer;
  1843. begin
  1844. AddCount:=0;
  1845. while (Lines^.Count<I+1) do
  1846. begin
  1847. Lines^.Insert(NewLine(''));
  1848. Inc(AddCount);
  1849. end;
  1850. if AddCount>0 then
  1851. LimitsChanged;
  1852. L:=Lines^.At(I);
  1853. if assigned(L^.Text) then
  1854. DisposeStr(L^.Text);
  1855. L^.Text:=NewStr(S);
  1856. end;
  1857. procedure TCodeEditor.SetLineBreakState(I : sw_integer;b : boolean);
  1858. var PL : PLine;
  1859. begin
  1860. if (i>0) and (i<=Lines^.Count) then
  1861. PL:=Lines^.At(i-1)
  1862. else
  1863. exit;
  1864. if assigned(PL) then
  1865. PL^.isbreakpoint:=b;
  1866. DrawView;
  1867. end;
  1868. function TCodeEditor.GetDisplayText(I: sw_integer): string;
  1869. begin
  1870. GetDisplayText:=ExtractTabs(GetLineText(I),TabSize);
  1871. end;
  1872. procedure TCodeEditor.SetDisplayText(I: sw_integer;const S: string);
  1873. begin
  1874. { I disagree here
  1875. I don't want the editor to change the position of the tabs
  1876. in my makefiles !! PM
  1877. if ((Flags and efUseTabCharacters)<>0) and (TabSize>0) then
  1878. SetLineText(I,CompressUsingTabs(S,TabSize))
  1879. else }
  1880. SetLineText(I,S);
  1881. end;
  1882. procedure TCodeEditor.GetDisplayTextFormat(I: sw_integer;var DT,DF:string);
  1883. var
  1884. L : PLine;
  1885. P,PAdd : SW_Integer;
  1886. begin
  1887. DF:='';
  1888. DT:='';
  1889. if I<Lines^.Count then
  1890. begin
  1891. L:=Lines^.At(I);
  1892. if assigned(L^.Text) then
  1893. begin
  1894. if assigned(L^.Format)=false then DF:='' else
  1895. DF:=L^.Format^;
  1896. DT:=L^.Text^;
  1897. p:=0;
  1898. while p<length(DT) do
  1899. begin
  1900. inc(p);
  1901. if DT[p]=#9 then
  1902. begin
  1903. PAdd:=TabSize-((p-1) mod TabSize);
  1904. if DF<>'' then
  1905. DF:=copy(DF,1,P-1)+CharStr(DF[p],PAdd)+copy(DF,P+1,255);
  1906. DT:=copy(DT,1,P-1)+CharStr(' ',PAdd)+copy(DT,P+1,255);
  1907. inc(P,PAdd-1);
  1908. end;
  1909. end;
  1910. end;
  1911. end;
  1912. end;
  1913. function TCodeEditor.GetLineFormat(I: sw_integer): string;
  1914. var P: PLine;
  1915. S: string;
  1916. begin
  1917. if I<GetLineCount then P:=Lines^.At(I) else P:=nil;
  1918. if (P=nil) or (P^.Format=nil) then S:='' else
  1919. S:=P^.Format^;
  1920. GetLineFormat:=S;
  1921. end;
  1922. procedure TCodeEditor.SetLineFormat(I: sw_integer;const S: string);
  1923. var P: PLine;
  1924. begin
  1925. if I<GetLineCount then
  1926. begin
  1927. P:=Lines^.At(I);
  1928. if P^.Format<>nil then DisposeStr(P^.Format);
  1929. P^.Format:=NewStr(S);
  1930. end;
  1931. end;
  1932. procedure TCodeEditor.DeleteAllLines;
  1933. begin
  1934. if Assigned(Lines) then
  1935. Lines^.FreeAll;
  1936. end;
  1937. procedure TCodeEditor.DeleteLine(I: sw_integer);
  1938. var
  1939. CP : Tpoint;
  1940. begin
  1941. if I<Lines^.Count then
  1942. begin
  1943. if StoreUndo then
  1944. begin
  1945. CP.X:=0;CP.Y:=I;
  1946. AddAction(eaDeleteLine,CP,CP,GetLineText(I));
  1947. end;
  1948. Lines^.AtFree(I);
  1949. end;
  1950. end;
  1951. procedure TCodeEditor.AddLine(const S: string);
  1952. begin
  1953. Lines^.Insert(NewLine(S));
  1954. end;
  1955. function TCodeEditor.GetSpecSymbolCount(SpecClass: TSpecSymbolClass): integer;
  1956. begin
  1957. GetSpecSymbolCount:=0;
  1958. end;
  1959. function TCodeEditor.GetSpecSymbol(SpecClass: TSpecSymbolClass; Index: integer): string;
  1960. begin
  1961. GetSpecSymbol:='';
  1962. Abstract;
  1963. end;
  1964. function TCodeEditor.IsReservedWord(const S: string): boolean;
  1965. begin
  1966. IsReservedWord:=false;
  1967. end;
  1968. function TCodeEditor.TranslateCodeTemplate(const Shortcut: string; ALines: PUnsortedStringCollection): boolean;
  1969. begin
  1970. TranslateCodeTemplate:=false;
  1971. end;
  1972. function TCodeEditor.CompleteCodeWord(const WordS: string; var Text: string): boolean;
  1973. begin
  1974. CompleteCodeWord:=false;
  1975. end;
  1976. function TCodeEditor.GetCodeCompleteWord: string;
  1977. begin
  1978. GetCodeCompleteWord:=GetStr(CodeCompleteWord);
  1979. end;
  1980. procedure TCodeEditor.SetCodeCompleteWord(const S: string);
  1981. begin
  1982. if Assigned(CodeCompleteWord) then DisposeStr(CodeCompleteWord);
  1983. CodeCompleteWord:=NewStr(S);
  1984. if S<>'' then
  1985. SetCompleteState(csOffering)
  1986. else
  1987. SetCompleteState(csInactive);
  1988. end;
  1989. procedure TCodeEditor.ClearCodeCompleteWord;
  1990. begin
  1991. SetCodeCompleteWord('');
  1992. SetCompleteState(csInactive);
  1993. end;
  1994. procedure TCodeEditor.Indent;
  1995. var S, PreS: string;
  1996. Shift: integer;
  1997. begin
  1998. S:=GetLineText(CurPos.Y);
  1999. if CurPos.Y>0 then
  2000. PreS:=RTrim(GetLineText(CurPos.Y-1),(Flags and efUseTabCharacters)=0)
  2001. else
  2002. PreS:='';
  2003. if CurPos.X>=length(PreS) then
  2004. Shift:=TabSize
  2005. else
  2006. begin
  2007. Shift:=1;
  2008. while (CurPos.X+Shift<length(PreS)) and (PreS[CurPos.X+Shift]<>' ') do
  2009. Inc(Shift);
  2010. end;
  2011. SetLineText(CurPos.Y,RExpand(copy(S,1,CurPos.X+1),CurPos.X+1)+CharStr(' ',Shift)+copy(S,CurPos.X+2,255));
  2012. SetCurPtr(CurPos.X+Shift,CurPos.Y);
  2013. UpdateAttrs(CurPos.Y,attrAll);
  2014. DrawLines(CurPos.Y);
  2015. SetModified(true);
  2016. end;
  2017. procedure TCodeEditor.CharLeft;
  2018. begin
  2019. if CurPos.X=0 then Exit;
  2020. SetCurPtr(CurPos.X-1,CurPos.Y);
  2021. end;
  2022. procedure TCodeEditor.CharRight;
  2023. begin
  2024. if CurPos.X>=MaxLineLength then
  2025. Exit;
  2026. SetCurPtr(CurPos.X+1,CurPos.Y);
  2027. end;
  2028. procedure TCodeEditor.WordLeft;
  2029. var X, Y: sw_integer;
  2030. Line: string;
  2031. GotIt,FoundNonSeparator: boolean;
  2032. begin
  2033. X:=CurPos.X;
  2034. Y:=CurPos.Y;
  2035. GotIt:=false;
  2036. FoundNonSeparator:=false;
  2037. while (Y>=0) do
  2038. begin
  2039. if Y=CurPos.Y then
  2040. begin
  2041. X:=length(GetDisplayText(Y));
  2042. if CurPos.X<X then
  2043. X:=CurPos.X; Dec(X);
  2044. if (X=-1) then
  2045. begin
  2046. Dec(Y);
  2047. if Y>=0 then
  2048. X:=length(GetDisplayText(Y));
  2049. Break;
  2050. end;
  2051. end
  2052. else
  2053. X:=length(GetDisplayText(Y))-1;
  2054. Line:=GetDisplayText(Y);
  2055. while (X>=0) and (GotIt=false) do
  2056. begin
  2057. if FoundNonSeparator then
  2058. begin
  2059. if IsWordSeparator(Line[X+1]) then
  2060. begin
  2061. Inc(X);
  2062. GotIt:=true;
  2063. Break;
  2064. end;
  2065. end
  2066. else
  2067. if not IsWordSeparator(Line[X+1]) then
  2068. FoundNonSeparator:=true;
  2069. Dec(X);
  2070. if (X=0) and (IsWordSeparator(Line[1])=false) then
  2071. begin
  2072. GotIt:=true;
  2073. Break;
  2074. end;
  2075. end;
  2076. if GotIt then
  2077. Break;
  2078. X:=0;
  2079. Dec(Y);
  2080. if Y>=0 then
  2081. begin
  2082. X:=length(GetDisplayText(Y));
  2083. Break;
  2084. end;
  2085. end;
  2086. if Y<0 then Y:=0; if X<0 then X:=0;
  2087. SetCurPtr(X,Y);
  2088. end;
  2089. procedure TCodeEditor.WordRight;
  2090. var X, Y: sw_integer;
  2091. Line: string;
  2092. GotIt: boolean;
  2093. begin
  2094. X:=CurPos.X; Y:=CurPos.Y; GotIt:=false;
  2095. while (Y<GetLineCount) do
  2096. begin
  2097. if Y=CurPos.Y then
  2098. begin
  2099. X:=CurPos.X; Inc(X);
  2100. if (X>length(GetDisplayText(Y))-1) then
  2101. begin Inc(Y); X:=0; end;
  2102. end else X:=0;
  2103. Line:=GetDisplayText(Y);
  2104. while (X<=length(Line)+1) and (GotIt=false) and (Line<>'') do
  2105. begin
  2106. if X=length(Line)+1 then begin GotIt:=true; Dec(X); Break end;
  2107. if IsWordSeparator(Line[X]) then
  2108. begin
  2109. while (Y<GetLineCount) and
  2110. (X<=length(Line)) and (IsWordSeparator(Line[X])) do
  2111. begin
  2112. Inc(X);
  2113. if X>=length(Line) then
  2114. begin GotIt:=true; Dec(X); Break; end;
  2115. end;
  2116. if (GotIt=false) and (X<length(Line)) then
  2117. begin
  2118. Dec(X);
  2119. GotIt:=true;
  2120. Break;
  2121. end;
  2122. end;
  2123. Inc(X);
  2124. end;
  2125. if GotIt then Break;
  2126. X:=0;
  2127. Inc(Y);
  2128. if (Y<GetLineCount) then
  2129. begin
  2130. Line:=GetDisplayText(Y);
  2131. if (Line<>'') and (IsWordSeparator(Line[1])=false) then Break;
  2132. end;
  2133. end;
  2134. if Y=GetLineCount then Y:=GetLineCount-1;
  2135. SetCurPtr(X,Y);
  2136. end;
  2137. procedure TCodeEditor.LineStart;
  2138. begin
  2139. SetCurPtr(0,CurPos.Y);
  2140. end;
  2141. procedure TCodeEditor.LineEnd;
  2142. var
  2143. s : string;
  2144. i : longint;
  2145. begin
  2146. if CurPos.Y<GetLineCount then
  2147. begin
  2148. s:=GetDisplayText(CurPos.Y);
  2149. i:=length(s);
  2150. while (i>0) and (s[i]=' ') do
  2151. dec(i);
  2152. SetCurPtr(i,CurPos.Y);
  2153. end
  2154. else
  2155. SetCurPtr(0,CurPos.Y);
  2156. end;
  2157. procedure TCodeEditor.LineUp;
  2158. begin
  2159. if CurPos.Y>0 then
  2160. SetCurPtr(CurPos.X,CurPos.Y-1);
  2161. end;
  2162. procedure TCodeEditor.LineDown;
  2163. begin
  2164. if CurPos.Y<GetLineCount-1 then
  2165. SetCurPtr(CurPos.X,CurPos.Y+1);
  2166. end;
  2167. procedure TCodeEditor.PageUp;
  2168. begin
  2169. ScrollTo(Delta.X,Max(Delta.Y-Size.Y,0));
  2170. SetCurPtr(CurPos.X,Max(0,CurPos.Y-(Size.Y)));
  2171. end;
  2172. procedure TCodeEditor.PageDown;
  2173. begin
  2174. ScrollTo(Delta.X,Min(Delta.Y+Size.Y,GetLineCount-1));
  2175. SetCurPtr(CurPos.X,Min(GetLineCount-1,CurPos.Y+(Size.Y{-1})));
  2176. end;
  2177. procedure TCodeEditor.TextStart;
  2178. begin
  2179. SetCurPtr(0,0);
  2180. end;
  2181. procedure TCodeEditor.TextEnd;
  2182. var s : string;
  2183. i : longint;
  2184. begin
  2185. s:=GetDisplayText(GetLineCount-1);
  2186. i:=length(s);
  2187. while (i>0) and (s[i]=' ') do
  2188. dec(i);
  2189. SetCurPtr(i,GetLineCount-1);
  2190. end;
  2191. procedure TCodeEditor.JumpSelStart;
  2192. begin
  2193. if ValidBlock then
  2194. SetCurPtr(SelStart.X,SelStart.Y);
  2195. end;
  2196. procedure TCodeEditor.JumpSelEnd;
  2197. begin
  2198. if ValidBlock then
  2199. SetCurPtr(SelEnd.X,SelEnd.Y);
  2200. end;
  2201. procedure TCodeEditor.JumpMark(MarkIdx: integer);
  2202. begin
  2203. if (MarkIdx<Low(Bookmarks)) or (MarkIdx>High(Bookmarks)) then
  2204. begin ErrorBox('Invalid mark index ('+IntToStr(MarkIdx)+')',nil); Exit; end;
  2205. with Bookmarks[MarkIdx] do
  2206. if Valid=false then
  2207. InformationBox('Mark '+IntToStr(MarkIdx)+' not set.',nil)
  2208. else
  2209. SetCurPtr(Pos.X,Pos.Y);
  2210. end;
  2211. procedure TCodeEditor.DefineMark(MarkIdx: integer);
  2212. begin
  2213. if (MarkIdx<Low(Bookmarks)) or (MarkIdx>High(Bookmarks)) then
  2214. begin
  2215. ErrorBox('Invalid mark index ('+IntToStr(MarkIdx)+')',nil);
  2216. Exit;
  2217. end;
  2218. with Bookmarks[MarkIdx] do
  2219. begin
  2220. Pos:=CurPos;
  2221. Valid:=true;
  2222. end;
  2223. end;
  2224. procedure TCodeEditor.JumpToLastCursorPos;
  2225. {$ifdef Undo}
  2226. var
  2227. pa : PEditorAction;
  2228. {$endif Undo}
  2229. begin
  2230. {$ifdef Undo}
  2231. if (UndoList^.count>0) and (RedoList^.count=0) then
  2232. begin
  2233. { Or should we just call Undo ?? PM }
  2234. pa:=UndoList^.At(UndoList^.count-1);
  2235. if (pa^.action=eaMoveCursor) then
  2236. SetCurPtr(pa^.StartPos.X,pa^.StartPos.Y);
  2237. end;
  2238. {$else not Undo}
  2239. NotImplemented;
  2240. {$endif Undo}
  2241. end;
  2242. function TCodeEditor.InsertLine: Sw_integer;
  2243. var Ind: Sw_integer;
  2244. S,IndentStr: string;
  2245. procedure CalcIndent(LineOver: Sw_integer);
  2246. begin
  2247. if (LineOver<0) or (LineOver>GetLineCount) then Ind:=0 else
  2248. begin
  2249. IndentStr:=GetLineText(LineOver);
  2250. Ind:=0;
  2251. while (Ind<length(IndentStr)) and (IndentStr[Ind+1]=' ') do
  2252. Inc(Ind);
  2253. end;
  2254. IndentStr:=CharStr(' ',Ind);
  2255. end;
  2256. var SelBack: sw_integer;
  2257. SCP: TPoint;
  2258. HoldUndo : Boolean;
  2259. begin
  2260. if IsReadOnly then begin InsertLine:=-1; Exit; end;
  2261. Lock;
  2262. SCP:=CurPos;
  2263. HoldUndo:=StoreUndo;
  2264. StoreUndo:=false;
  2265. if CurPos.Y<GetLineCount then S:=GetLineText(CurPos.Y) else S:='';
  2266. if Overwrite=false then
  2267. begin
  2268. SelBack:=0;
  2269. if GetLineCount>0 then
  2270. begin
  2271. S:=GetDisplayText(CurPos.Y);
  2272. SelBack:=length(S)-SelEnd.X;
  2273. SetDisplayText(CurPos.Y,RTrim(S,(Flags and efUseTabCharacters)=0));
  2274. end;
  2275. SetDisplayText(CurPos.Y,copy(S,1,CurPos.X-1+1));
  2276. CalcIndent(CurPos.Y);
  2277. Lines^.AtInsert(CurPos.Y+1,NewLine(IndentStr+copy(S,CurPos.X+1,255)));
  2278. LimitsChanged;
  2279. (* if PointOfs(SelStart)<>PointOfs(SelEnd) then { !!! check it - it's buggy !!! }
  2280. begin SelEnd.Y:=CurPos.Y+1; SelEnd.X:=length(GetLineText(CurPos.Y+1))-SelBack; end;*)
  2281. UpdateAttrs(CurPos.Y,attrAll);
  2282. SetCurPtr(Ind,CurPos.Y+1);
  2283. {$ifdef Undo}
  2284. StoreUndo:=HoldUndo;
  2285. Addaction(eaInsertLine,SCP,CurPos,IndentStr);
  2286. StoreUndo:=false;
  2287. {$endif Undo}
  2288. AdjustSelection(CurPos.X-SCP.X,CurPos.Y-SCP.Y);
  2289. end else
  2290. begin
  2291. CalcIndent(CurPos.Y);
  2292. if CurPos.Y=GetLineCount-1 then
  2293. begin
  2294. Lines^.Insert(NewLine(IndentStr));
  2295. AdjustSelection(0,1);
  2296. LimitsChanged;
  2297. {$ifdef Undo}
  2298. StoreUndo:=HoldUndo;
  2299. UpdateAttrs(CurPos.Y,attrAll);
  2300. SetCurPtr(Ind,CurPos.Y+1);
  2301. Addaction(eaInsertLine,SCP,CurPos,IndentStr);
  2302. StoreUndo:=false;
  2303. {$endif Undo}
  2304. end
  2305. else
  2306. begin
  2307. UpdateAttrs(CurPos.Y,attrAll);
  2308. StoreUndo:=HoldUndo;
  2309. SetCurPtr(Ind,CurPos.Y+1);
  2310. StoreUndo:=false;
  2311. end;
  2312. end;
  2313. DrawLines(CurPos.Y);
  2314. StoreUndo:=HoldUndo;
  2315. SetModified(true);
  2316. Unlock;
  2317. end;
  2318. procedure TCodeEditor.BreakLine;
  2319. begin
  2320. NotImplemented; Exit;
  2321. end;
  2322. procedure TCodeEditor.BackSpace;
  2323. var S,PreS: string;
  2324. OI,CI,CP,Y,TX: Sw_integer;
  2325. SCP,SC1 : TPoint;
  2326. HoldUndo : Boolean;
  2327. begin
  2328. if IsReadOnly then Exit;
  2329. Lock;
  2330. SCP:=CurPos;
  2331. HoldUndo:=StoreUndo;
  2332. StoreUndo:=false;
  2333. if CurPos.X=0 then
  2334. begin
  2335. if CurPos.Y>0 then
  2336. begin
  2337. S:=GetLineText(CurPos.Y-1);
  2338. SetLineText(CurPos.Y-1,S+GetLineText(CurPos.Y));
  2339. SC1.X:=Length(S);SC1.Y:=CurPOS.Y-1;
  2340. StoreUndo:=HoldUndo;
  2341. AddAction(eaDeleteLine,SCP,SC1,GetLineText(CurPos.Y));
  2342. StoreUndo:=false;
  2343. DeleteLine(CurPos.Y);
  2344. LimitsChanged;
  2345. SetCurPtr(length(S),CurPos.Y-1);
  2346. end;
  2347. end
  2348. else
  2349. begin
  2350. S:=GetDisplayText(CurPos.Y);
  2351. CP:=CurPos.X-1;
  2352. if (Flags and efBackspaceUnindents)<>0 then
  2353. if Trim(copy(S,1,CP+1))='' then
  2354. begin
  2355. Y:=CurPos.Y;
  2356. while (Y>0) do
  2357. begin
  2358. Dec(Y);
  2359. PreS:=GetDisplayText(Y);
  2360. if Trim(copy(PreS,1,CP+1))<>'' then Break;
  2361. end;
  2362. if Y<0 then PreS:='';
  2363. { while (CP>0) and
  2364. ( (CP>length(S)) or (S[CP]=' ') ) and
  2365. ( (CP>length(PreS)) or (PreS[CP]<>' ') ) do
  2366. Dec(CP);}
  2367. TX:=0;
  2368. while (TX<length(PreS)) and (PreS[TX+1]=' ') do
  2369. Inc(TX);
  2370. if TX<CP then CP:=TX;
  2371. end;
  2372. S:=GetLineText(CurPos.Y);
  2373. OI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  2374. CI:=LinePosToCharIdx(CurPos.Y,CP);
  2375. SetLineText(CurPos.Y,copy(S,1,CI-1)+copy(S,OI,255));
  2376. SetCurPtr(CP,CurPos.Y);
  2377. {$ifdef Undo}
  2378. StoreUndo:=HoldUndo;
  2379. Addaction(eaDeleteText,SCP,CurPos,Copy(S,CI,OI-CI));
  2380. StoreUndo:=false;
  2381. {$endif Undo}
  2382. end;
  2383. UpdateAttrs(CurPos.Y,attrAll);
  2384. AdjustSelection(CurPos.X-SCP.X,CurPos.Y-SCP.Y);
  2385. DrawLines(CurPos.Y);
  2386. StoreUndo:=HoldUndo;
  2387. SetModified(true);
  2388. Unlock;
  2389. end;
  2390. procedure TCodeEditor.DelChar;
  2391. var S: string;
  2392. SDX,SDY,CI : sw_integer;
  2393. HoldUndo : boolean;
  2394. SCP : TPoint;
  2395. begin
  2396. if IsReadOnly then Exit;
  2397. Lock;
  2398. HoldUndo:=StoreUndo;
  2399. StoreUndo:=false;
  2400. S:=GetLineText(CurPos.Y);
  2401. if CurPos.X=length(S) then
  2402. begin
  2403. if CurPos.Y<GetLineCount-1 then
  2404. begin
  2405. SetLineText(CurPos.Y,S+GetLineText(CurPos.Y+1));
  2406. StoreUndo:=HoldUndo;
  2407. SCP.X:=0;SCP.Y:=CurPos.Y+1;
  2408. AddAction(eaDeleteLine,SCP,CurPos,GetLineText(CurPos.Y+1));
  2409. StoreUndo:=false;
  2410. DeleteLine(CurPos.Y+1);
  2411. LimitsChanged;
  2412. SDX:=0; SDY:=-1;
  2413. end;
  2414. end
  2415. else
  2416. begin
  2417. { Problem if S[CurPos.X+1]=TAB !! PM }
  2418. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  2419. if S[CI]=TAB then
  2420. begin
  2421. S:=Copy(S,1,CI-1)+CharStr(' ',TabSize-1)+Copy(S,CI+1,255);
  2422. {$ifdef Undo}
  2423. StoreUndo:=HoldUndo;
  2424. Addaction(eaDeleteText,CurPos,CurPos,' ');
  2425. StoreUndo:=false;
  2426. {$endif Undo}
  2427. end
  2428. else
  2429. begin
  2430. {$ifdef Undo}
  2431. StoreUndo:=HoldUndo;
  2432. Addaction(eaDeleteText,CurPos,CurPos,S[CI]);
  2433. StoreUndo:=false;
  2434. {$endif Undo}
  2435. Delete(S,CI,1);
  2436. end;
  2437. SetLineText(CurPos.Y,S);
  2438. SDX:=-1; SDY:=0;
  2439. end;
  2440. SetCurPtr(CurPos.X,CurPos.Y);
  2441. UpdateAttrs(CurPos.Y,attrAll);
  2442. AdjustSelection(SDX,SDY);
  2443. DrawLines(CurPos.Y);
  2444. StoreUndo:=HoldUndo;
  2445. SetModified(true);
  2446. Unlock;
  2447. end;
  2448. procedure TCodeEditor.DelWord;
  2449. var
  2450. SP,EP : TPoint;
  2451. SelSize : sw_integer;
  2452. begin
  2453. if IsReadOnly then Exit;
  2454. Lock;
  2455. SP:=SelStart;
  2456. EP:=SelEnd;
  2457. SelectWord;
  2458. SelSize:=SelEnd.X-SelStart.X;
  2459. DelSelect;
  2460. SetSelection(SP,EP);
  2461. AdjustSelectionPos(CurPos.X,CurPos.Y,SelSize,0);
  2462. SetModified(true);
  2463. Unlock;
  2464. end;
  2465. procedure TCodeEditor.DelStart;
  2466. var S: string;
  2467. begin
  2468. if IsReadOnly then Exit;
  2469. Lock;
  2470. S:=GetLineText(CurPos.Y);
  2471. if (S<>'') and (CurPos.X<>0) then
  2472. begin
  2473. SetLineText(CurPos.Y,copy(S,LinePosToCharIdx(CurPos.Y,CurPos.X),255));
  2474. SetCurPtr(0,CurPos.Y);
  2475. UpdateAttrs(CurPos.Y,attrAll);
  2476. DrawLines(CurPos.Y);
  2477. SetModified(true);
  2478. end;
  2479. Unlock;
  2480. end;
  2481. procedure TCodeEditor.DelEnd;
  2482. var S: string;
  2483. begin
  2484. if IsReadOnly then Exit;
  2485. Lock;
  2486. S:=GetLineText(CurPos.Y);
  2487. if (S<>'') and (CurPos.X<>length(S)) then
  2488. begin
  2489. SetLineText(CurPos.Y,copy(S,1,LinePosToCharIdx(CurPos.Y,CurPos.X)-1));
  2490. SetCurPtr(CurPos.X,CurPos.Y);
  2491. UpdateAttrs(CurPos.Y,attrAll);
  2492. DrawLines(CurPos.Y);
  2493. SetModified(true);
  2494. end;
  2495. Unlock;
  2496. end;
  2497. procedure TCodeEditor.DelLine;
  2498. var
  2499. HoldUndo : boolean;
  2500. SP : TPoint;
  2501. begin
  2502. if IsReadOnly then Exit;
  2503. Lock;
  2504. if GetLineCount>0 then
  2505. begin
  2506. SP:=CurPos;
  2507. DeleteLine(CurPos.Y);
  2508. HoldUndo:=StoreUndo;
  2509. StoreUndo:=false;
  2510. LimitsChanged;
  2511. AdjustSelection(0,-1);
  2512. SetCurPtr(0,CurPos.Y);
  2513. UpdateAttrs(Max(0,CurPos.Y-1),attrAll);
  2514. DrawLines(CurPos.Y);
  2515. If HoldUndo then
  2516. with UndoList^.At(UndoList^.count-1)^ do
  2517. begin
  2518. EndPos:=CurPos;
  2519. StartPos:=SP;
  2520. end;
  2521. StoreUndo:=HoldUndo;
  2522. SetModified(true);
  2523. end;
  2524. Unlock;
  2525. end;
  2526. procedure TCodeEditor.InsMode;
  2527. begin
  2528. SetInsertMode(Overwrite);
  2529. end;
  2530. function TCodeEditor.GetCurrentWord : string;
  2531. const WordChars = ['A'..'Z','a'..'z','0'..'9','_'];
  2532. var P : TPoint;
  2533. S : String;
  2534. StartPos,EndPos : byte;
  2535. begin
  2536. P:=CurPos;
  2537. S:=GetLineText(P.Y);
  2538. StartPos:=P.X+1;
  2539. EndPos:=StartPos;
  2540. if not (S[StartPos] in WordChars) then
  2541. GetCurrentWord:=''
  2542. else
  2543. begin
  2544. While (StartPos>0) and (S[StartPos-1] in WordChars) do
  2545. Dec(StartPos);
  2546. While (EndPos<Length(S)) and (S[EndPos+1] in WordChars) do
  2547. Inc(EndPos);
  2548. GetCurrentWord:=Copy(S,StartPos,EndPos-StartPos+1);
  2549. end;
  2550. end;
  2551. procedure TCodeEditor.StartSelect;
  2552. var P1,P2: TPoint;
  2553. begin
  2554. if ValidBlock=false then
  2555. begin
  2556. { SetSelection(SelStart,Limit);}
  2557. P1:=CurPos; P1.X:=0; P2:=CurPos; {P2.X:=length(GetLineText(P2.Y))+1;}
  2558. SetSelection(P1,P2);
  2559. end
  2560. else
  2561. SetSelection(CurPos,SelEnd);
  2562. if PointOfs(SelEnd)<PointOfs(SelStart) then
  2563. SetSelection(SelStart,SelStart);
  2564. CheckSels;
  2565. DrawView;
  2566. end;
  2567. procedure TCodeEditor.EndSelect;
  2568. var P: TPoint;
  2569. LS: sw_integer;
  2570. begin
  2571. P:=CurPos;
  2572. { P.X:=Min(SelEnd.X,length(GetLineText(SelEnd.Y)));}
  2573. LS:=length(GetLineText(SelEnd.Y));
  2574. if LS<P.X then P.X:=LS;
  2575. CheckSels;
  2576. SetSelection(SelStart,P);
  2577. DrawView;
  2578. end;
  2579. procedure TCodeEditor.DelSelect;
  2580. var LineDelta, LineCount, CurLine: Sw_integer;
  2581. StartX,EndX,LastX: Sw_integer;
  2582. S: string;
  2583. SPos : TPoint;
  2584. begin
  2585. if IsReadOnly or (ValidBlock=false) then Exit;
  2586. Lock;
  2587. LineCount:=(SelEnd.Y-SelStart.Y)+1;
  2588. LineDelta:=0; LastX:=CurPos.X;
  2589. CurLine:=SelStart.Y;
  2590. while (LineDelta<LineCount) do
  2591. begin
  2592. S:=GetDisplayText(CurLine);
  2593. if LineDelta=0 then StartX:=SelStart.X else StartX:=0;
  2594. if LineDelta=LineCount-1 then EndX:=SelEnd.X else EndX:=length(S);
  2595. if (LineDelta<LineCount-1) and ((StartX=0) and (EndX>=length(S))) then
  2596. begin
  2597. { delete the complete line }
  2598. DeleteLine(CurLine);
  2599. if CurLine>0 then
  2600. LastX:=length(GetDisplayText(CurLine-1))
  2601. else
  2602. LastX:=0;
  2603. end
  2604. else
  2605. begin
  2606. if StoreUndo then
  2607. begin
  2608. SPos.X:=StartX;
  2609. SPos.Y:=CurLine;
  2610. AddAction(eaDeleteText,SPos,SPos,Copy(S,StartX+1,EndX-StartX));
  2611. end;
  2612. SetDisplayText(CurLine,RExpand(copy(S,1,StartX),StartX)+copy(S,EndX+1,255));
  2613. LastX:=StartX;
  2614. if (StartX=0) and (0<LineDelta) and
  2615. not(((LineDelta=LineCount-1) and (StartX=0) and (StartX=EndX))) then
  2616. begin
  2617. S:=GetDisplayText(CurLine-1);
  2618. SetDisplayText(CurLine-1,S+GetLineText(CurLine));
  2619. DeleteLine(CurLine);
  2620. LastX:=length(S);
  2621. end
  2622. else
  2623. Inc(CurLine);
  2624. end;
  2625. Inc(LineDelta);
  2626. end;
  2627. HideSelect;
  2628. SetCurPtr(LastX,CurLine-1);
  2629. UpdateAttrs(CurPos.Y,attrAll);
  2630. DrawLines(CurPos.Y);
  2631. SetModified(true);
  2632. UnLock;
  2633. end;
  2634. procedure TCodeEditor.HideSelect;
  2635. begin
  2636. SetSelection(CurPos,CurPos);
  2637. DrawLines(Delta.Y);
  2638. end;
  2639. procedure TCodeEditor.CopyBlock;
  2640. var Temp: PCodeEditor;
  2641. R: TRect;
  2642. begin
  2643. if IsReadOnly or (ValidBlock=false) then Exit;
  2644. Lock;
  2645. GetExtent(R);
  2646. New(Temp, Init(R, nil, nil, nil,0));
  2647. Temp^.InsertFrom(@Self);
  2648. Temp^.SelectAll(true);
  2649. { this selects one line too much because
  2650. we have a empty line at creation to avoid
  2651. negative line problems so we need to decrease SelEnd.Y }
  2652. Dec(Temp^.SelEnd.Y);
  2653. InsertFrom(Temp);
  2654. Dispose(Temp, Done);
  2655. UnLock;
  2656. end;
  2657. procedure TCodeEditor.MoveBlock;
  2658. var Temp: PCodeEditor;
  2659. R: TRect;
  2660. OldPos: TPoint;
  2661. begin
  2662. if IsReadOnly then Exit;
  2663. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  2664. Lock;
  2665. GetExtent(R);
  2666. New(Temp, Init(R, nil, nil, nil,0));
  2667. Temp^.InsertFrom(@Self);
  2668. OldPos:=CurPos;
  2669. if CurPos.Y>SelStart.Y then
  2670. Dec(OldPos.Y,Temp^.GetLineCount-1);
  2671. DelSelect;
  2672. SetCurPtr(OldPos.X,OldPos.Y);
  2673. InsertFrom(Temp);
  2674. Dispose(Temp, Done);
  2675. UnLock;
  2676. end;
  2677. procedure TCodeEditor.IndentBlock;
  2678. var
  2679. ey,i : Sw_integer;
  2680. S : String;
  2681. begin
  2682. if IsReadOnly then Exit;
  2683. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  2684. Lock;
  2685. ey:=selend.y;
  2686. if selend.x=0 then
  2687. dec(ey);
  2688. for i:=selstart.y to ey do
  2689. begin
  2690. S:=GetLineText(i);
  2691. SetLineText(i,' '+S);
  2692. end;
  2693. SetCurPtr(CurPos.X,CurPos.Y);
  2694. UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
  2695. DrawLines(CurPos.Y);
  2696. SetModified(true);
  2697. UnLock;
  2698. end;
  2699. procedure TCodeEditor.UnindentBlock;
  2700. var
  2701. ey,i : Sw_integer;
  2702. S : String;
  2703. begin
  2704. if IsReadOnly then Exit;
  2705. if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
  2706. Lock;
  2707. ey:=selend.y;
  2708. if selend.x=0 then
  2709. dec(ey);
  2710. for i:=selstart.y to ey do
  2711. begin
  2712. S:=GetLineText(i);
  2713. if (length(s)>1) and (S[1]=' ') then
  2714. Delete(s,1,1);
  2715. SetLineText(i,S);
  2716. end;
  2717. SetCurPtr(CurPos.X,CurPos.Y);
  2718. UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
  2719. DrawLines(CurPos.Y);
  2720. SetModified(true);
  2721. UnLock;
  2722. end;
  2723. procedure TCodeEditor.SelectWord;
  2724. const WordChars = ['A'..'Z','a'..'z','0'..'9','_'];
  2725. var S : String;
  2726. StartPos,EndPos : byte;
  2727. A,B: TPoint;
  2728. begin
  2729. A:=CurPos;
  2730. B:=CurPos;
  2731. S:=GetLineText(A.Y);
  2732. StartPos:=A.X+1;
  2733. EndPos:=StartPos;
  2734. if not (S[StartPos] in WordChars) then
  2735. exit
  2736. else
  2737. begin
  2738. While (StartPos>0) and (S[StartPos-1] in WordChars) do
  2739. Dec(StartPos);
  2740. While (EndPos<Length(S)) and (S[EndPos+1] in WordChars) do
  2741. Inc(EndPos);
  2742. A.X:=StartPos-1;
  2743. B.X:=EndPos;
  2744. SetSelection(A,B);
  2745. end;
  2746. end;
  2747. procedure TCodeEditor.SelectLine;
  2748. var A,B: TPoint;
  2749. begin
  2750. if CurPos.Y<GetLineCount then
  2751. begin
  2752. A.Y:=CurPos.Y; A.X:=0;
  2753. B.Y:=CurPos.Y+1; B.X:=0;
  2754. SetSelection(A,B);
  2755. end;
  2756. end;
  2757. procedure TCodeEditor.WriteBlock;
  2758. var FileName: string;
  2759. S: PBufStream;
  2760. begin
  2761. if ValidBlock=false then Exit;
  2762. FileName:='';
  2763. if EditorDialog(edWriteBlock, @FileName) <> cmCancel then
  2764. begin
  2765. FileName := FExpand(FileName);
  2766. New(S, Init(FileName, stCreate, 4096));
  2767. if (S=nil) or (S^.Status<>stOK) then
  2768. EditorDialog(edCreateError,@FileName)
  2769. else
  2770. if SaveAreaToStream(S,SelStart,SelEnd)=false then
  2771. EditorDialog(edWriteError,@FileName);
  2772. if Assigned(S) then Dispose(S, Done);
  2773. end;
  2774. end;
  2775. procedure TCodeEditor.ReadBlock;
  2776. var FileName: string;
  2777. S: PBufStream;
  2778. E: PCodeEditor;
  2779. R: TRect;
  2780. begin
  2781. FileName:='';
  2782. if EditorDialog(edReadBlock, @FileName) <> cmCancel then
  2783. begin
  2784. FileName := FExpand(FileName);
  2785. New(S, Init(FileName, stOpenRead, 4096));
  2786. if (S=nil) or (S^.Status<>stOK) then
  2787. EditorDialog(edReadError,@FileName)
  2788. else
  2789. begin
  2790. R.Assign(0,0,0,0);
  2791. New(E, Init(R,nil,nil,nil,0));
  2792. if E^.LoadFromStream(S)=false then
  2793. EditorDialog(edReadError,@FileName)
  2794. else
  2795. begin
  2796. E^.SelectAll(true);
  2797. Self.InsertFrom(E);
  2798. end;
  2799. Dispose(E, Done);
  2800. end;
  2801. if Assigned(S) then Dispose(S, Done);
  2802. end;
  2803. end;
  2804. procedure TCodeEditor.PrintBlock;
  2805. begin
  2806. NotImplemented; Exit;
  2807. end;
  2808. procedure TCodeEditor.ExpandCodeTemplate;
  2809. var OSS,OSE: TPoint;
  2810. Line,ShortCut: string;
  2811. X,Y,I,LineIndent: sw_integer;
  2812. CodeLines: PUnsortedStringCollection;
  2813. begin
  2814. {
  2815. The usage of editing primitives in this routine make it pretty slow, but
  2816. its speed is still acceptable and they make the implementation of Undo
  2817. much easier... - Gabor
  2818. }
  2819. if IsReadOnly then Exit;
  2820. Lock;
  2821. Line:=GetDisplayText(CurPos.Y);
  2822. X:=CurPos.X; ShortCut:='';
  2823. if X<=length(Line) then
  2824. while (X>0) and (Line[X] in (NumberChars+AlphaChars)) do
  2825. begin
  2826. ShortCut:=Line[X]+ShortCut;
  2827. Dec(X);
  2828. end;
  2829. if ShortCut<>'' then
  2830. begin
  2831. New(CodeLines, Init(10,10));
  2832. if TranslateCodeTemplate(ShortCut,CodeLines) then
  2833. begin
  2834. LineIndent:=X;
  2835. SetCurPtr(X,CurPos.Y);
  2836. for I:=1 to length(ShortCut) do
  2837. DelChar;
  2838. for Y:=0 to CodeLines^.Count-1 do
  2839. begin
  2840. if Y>0 then
  2841. for X:=1 to LineIndent do { indent template lines to align }
  2842. AddChar(' '); { them to the first line }
  2843. Line:=CodeLines^.At(Y)^;
  2844. for X:=1 to length(Line) do
  2845. AddChar(Line[X]);
  2846. if Y<CodeLines^.Count-1 then
  2847. begin
  2848. InsertLine; { line break }
  2849. while CurPos.X>0 do { unindent }
  2850. begin
  2851. SetCurPtr(CurPos.X-1,CurPos.Y);
  2852. DelChar;
  2853. end;
  2854. end;
  2855. end;
  2856. end;
  2857. Dispose(CodeLines, Done);
  2858. end;
  2859. UnLock;
  2860. end;
  2861. procedure TCodeEditor.AddChar(C: char);
  2862. const OpenBrackets : string[10] = '[({';
  2863. CloseBrackets : string[10] = '])}';
  2864. var S,SC,TabS: string;
  2865. BI: byte;
  2866. CI,TabStart,LocTabSize : Sw_integer;
  2867. SP: TPoint;
  2868. HoldUndo : boolean;
  2869. begin
  2870. if IsReadOnly then Exit;
  2871. Lock;
  2872. SP:=CurPos;
  2873. HoldUndo:=StoreUndo;
  2874. StoreUndo:=false;
  2875. if (C<>TAB) or ((Flags and efUseTabCharacters)<>0) then
  2876. SC:=C
  2877. else
  2878. begin
  2879. LocTabSize:=TabSize - (CurPos.X mod TabSize);
  2880. if (CurPos.Y<=1) or ((Flags and efAutoIndent)=0) then
  2881. SC:=CharStr(' ',LocTabSize)
  2882. else
  2883. begin
  2884. S:=GetLineText(CurPos.Y-1);
  2885. BI:=CurPos.X+1;
  2886. while (BI<=Length(S)) and (S[BI]=' ') do
  2887. inc(BI);
  2888. if (BI=CurPos.X+1) or (BI>Length(S)) then
  2889. SC:=CharStr(' ',LocTabSize)
  2890. else
  2891. SC:=CharStr(' ',BI-CurPos.X-1);
  2892. end;
  2893. end;
  2894. S:=GetLineText(CurPos.Y);
  2895. if CharIdxToLinePos(CurPos.Y,length(S))<CurPos.X then
  2896. begin
  2897. S:=S+CharStr(' ',CurPos.X-CharIdxToLinePos(CurPos.Y,length(S)){-1});
  2898. SetLineText(CurPos.Y,S);
  2899. end;
  2900. CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
  2901. if (CI>0) and (S[CI]=TAB) then
  2902. begin
  2903. if CI=1 then
  2904. TabStart:=0
  2905. else
  2906. TabStart:=CharIdxToLinePos(CurPos.Y,CI-1)+1;
  2907. if SC=Tab then TabS:=Tab else
  2908. TabS:=CharStr(' ',CurPos.X-TabStart);
  2909. SetLineText(CurPos.Y,copy(S,1,CI-1)+TabS+SC+copy(S,CI+1,255));
  2910. SetCurPtr(CharIdxToLinePos(CurPos.Y,CI+length(TabS)+length(SC)),CurPos.Y);
  2911. end
  2912. else
  2913. begin
  2914. if Overwrite and (CI<=length(S)) then
  2915. SetLineText(CurPos.Y,copy(S,1,CI-1)+SC+copy(S,CI+length(SC),255))
  2916. else
  2917. SetLineText(CurPos.Y,copy(S,1,CI-1)+SC+copy(S,CI,255));
  2918. SetCurPtr(CharIdxToLinePos(CurPos.Y,CI+length(SC)),CurPos.Y);
  2919. end;
  2920. {$ifdef Undo}
  2921. { must be before CloseBrackets !! }
  2922. StoreUndo:=HoldUndo;
  2923. Addaction(eaInsertText,SP,CurPos,C);
  2924. StoreUndo:=false;
  2925. {$endif Undo}
  2926. if ((Flags and efAutoBrackets)<>0) then
  2927. begin
  2928. BI:=Pos(C,OpenBrackets);
  2929. if (BI>0) then
  2930. begin
  2931. StoreUndo:=HoldUndo;
  2932. AddChar(CloseBrackets[BI]);
  2933. StoreUndo:=false;
  2934. SetCurPtr(CurPos.X-1,CurPos.Y);
  2935. end;
  2936. end;
  2937. UpdateAttrs(CurPos.Y,attrAll);
  2938. AdjustSelection(CurPos.X-SP.X,CurPos.Y-SP.Y);
  2939. DrawLines(CurPos.Y);
  2940. StoreUndo:=HoldUndo;
  2941. SetModified(true);
  2942. UnLock;
  2943. end;
  2944. function TCodeEditor.ClipCopy: Boolean;
  2945. var OK: boolean;
  2946. begin
  2947. Lock;
  2948. {AddGroupedAction(eaCopy);
  2949. can we undo a copy ??
  2950. maybe as an Undo Paste in Clipboard !! }
  2951. OK:=Clipboard<>nil;
  2952. if OK then OK:=Clipboard^.InsertFrom(@Self);
  2953. ClipCopy:=OK;
  2954. UnLock;
  2955. end;
  2956. procedure TCodeEditor.ClipCut;
  2957. begin
  2958. if IsReadOnly then Exit;
  2959. Lock;
  2960. AddGroupedAction(eaCut);
  2961. DontConsiderShiftState:=true;
  2962. if Clipboard<>nil then
  2963. if Clipboard^.InsertFrom(@Self) then
  2964. begin
  2965. if not IsClipBoard then
  2966. DelSelect;
  2967. SetModified(true);
  2968. end;
  2969. CloseGroupedAction(eaCut);
  2970. UnLock;
  2971. DontConsiderShiftState:=false;
  2972. end;
  2973. procedure TCodeEditor.ClipPaste;
  2974. begin
  2975. if IsReadOnly then Exit;
  2976. DontConsiderShiftState:=true;
  2977. Lock;
  2978. AddGroupedAction(eaPaste);
  2979. if Clipboard<>nil then
  2980. begin
  2981. InsertFrom(Clipboard);
  2982. SetModified(true);
  2983. end;
  2984. CloseGroupedAction(eaPaste);
  2985. UnLock;
  2986. DontConsiderShiftState:=false;
  2987. end;
  2988. {$ifdef WinClipSupported}
  2989. function TCodeEditor.ClipPasteWin: Boolean;
  2990. var OK: boolean;
  2991. l,i : longint;
  2992. p,p10,p2,p13 : pchar;
  2993. s : string;
  2994. BPos,EPos,StorePos : TPoint;
  2995. first : boolean;
  2996. begin
  2997. Lock;
  2998. OK:=WinClipboardSupported;
  2999. if OK then
  3000. begin
  3001. first:=true;
  3002. StorePos:=CurPos;
  3003. i:=CurPos.Y;
  3004. l:=GetTextWinClipboardSize;
  3005. if l=0 then
  3006. OK:=false
  3007. else
  3008. OK:=GetTextWinClipBoardData(p,l);
  3009. if OK then
  3010. begin
  3011. AddGroupedAction(eaPasteWin);
  3012. p2:=p;
  3013. p13:=strpos(p,#13);
  3014. p10:=strpos(p,#10);
  3015. while assigned(p10) do
  3016. begin
  3017. if p13+1=p10 then
  3018. p13[0]:=#0
  3019. else
  3020. p10[0]:=#0;
  3021. s:=strpas(p2);
  3022. if first then
  3023. begin
  3024. { we need to cut the line in two
  3025. if not at end of line PM }
  3026. InsertLine;
  3027. SetCurPtr(StorePos.X,StorePos.Y);
  3028. InsertText(s);
  3029. first:=false;
  3030. end
  3031. else
  3032. begin
  3033. Inc(i);
  3034. Lines^.AtInsert(i,NewLine(s));
  3035. BPos.X:=0;BPos.Y:=i;
  3036. EPOS.X:=Length(s);EPos.Y:=i;
  3037. AddAction(eaInsertLine,BPos,EPos,S);
  3038. end;
  3039. if p13+1=p10 then
  3040. p13[0]:=#13
  3041. else
  3042. p10[0]:=#10;
  3043. p2:=@p10[1];
  3044. p13:=strpos(p2,#13);
  3045. p10:=strpos(p2,#10);
  3046. end;
  3047. if strlen(p2)>0 then
  3048. begin
  3049. s:=strpas(p2);
  3050. if not first then
  3051. SetCurPtr(0,i+1);
  3052. InsertText(s);
  3053. end;
  3054. SetCurPtr(StorePos.X,StorePos.Y);
  3055. SetModified(true);
  3056. UpdateAttrs(StorePos.Y,attrAll);
  3057. CloseGroupedAction(eaPasteWin);
  3058. Update;
  3059. { we must free the allocated memory }
  3060. freemem(p,l);
  3061. end;
  3062. end;
  3063. ClipPasteWin:=OK;
  3064. UnLock;
  3065. end;
  3066. function TCodeEditor.ClipCopyWin: Boolean;
  3067. var OK: boolean;
  3068. p,p2 : pchar;
  3069. s : string;
  3070. i,str_begin,str_end,NumLines,PcLength : longint;
  3071. begin
  3072. NumLines:=SelEnd.Y-SelStart.Y;
  3073. if (NumLines>0) or (SelEnd.X>SelStart.X) then
  3074. Inc(NumLines);
  3075. if NumLines=0 then
  3076. exit;
  3077. Lock;
  3078. { First calculate needed size }
  3079. { for newlines first + 1 for terminal #0 }
  3080. PcLength:=Length(EOL)*(NumLines-1)+1;
  3081. { overestimated but can not be that big PM }
  3082. for i:=SelStart.Y to SelEnd.Y do
  3083. PCLength:=PCLength+Length(GetLineText(i));
  3084. getmem(p,PCLength);
  3085. i:=SelStart.Y;
  3086. s:=GetLineText(i);
  3087. str_begin:=LinePosToCharIdx(i,SelStart.X);
  3088. if SelEnd.Y>SelStart.Y then
  3089. str_end:=255
  3090. else
  3091. str_end:=LinePosToCharIdx(i,SelEnd.X)-1;
  3092. s:=copy(s,str_begin,str_end-str_begin+1);
  3093. strpcopy(p,s);
  3094. p2:=strend(p);
  3095. inc(i);
  3096. while i<SelEnd.Y do
  3097. begin
  3098. strpcopy(p2,EOL+GetLineText(i));
  3099. p2:=strend(p2);
  3100. Inc(i);
  3101. end;
  3102. if SelEnd.Y>SelStart.Y then
  3103. begin
  3104. s:=copy(GetLineText(i),1,LinePosToCharIdx(i,SelEnd.X)-1);
  3105. strpcopy(p2,EOL+s);
  3106. end;
  3107. OK:=WinClipboardSupported;
  3108. if OK then
  3109. begin
  3110. OK:=SetTextWinClipBoardData(p,strlen(p));
  3111. end;
  3112. ClipCopyWin:=OK;
  3113. Freemem(p,PCLength);
  3114. UnLock;
  3115. end;
  3116. {$endif WinClipSupported}
  3117. procedure TCodeEditor.Undo;
  3118. {$ifdef Undo}
  3119. var
  3120. Temp,Idx,Last,Count : Longint;
  3121. Is_grouped : boolean;
  3122. {$endif Undo}
  3123. begin
  3124. {$ifdef Undo}
  3125. StoreUndo := False;
  3126. Lock;
  3127. if UndoList^.count > 0 then
  3128. begin
  3129. Last:=UndoList^.count-1;
  3130. if UndoList^.At(Last)^.Is_grouped_action then
  3131. begin
  3132. Count:=UndoList^.At(Last)^.ActionCount;
  3133. Dec(Last);
  3134. Is_grouped:=true;
  3135. end
  3136. else
  3137. begin
  3138. Count:=1;
  3139. Is_grouped:=false;
  3140. end;
  3141. for Idx:=Last downto Last-Count+1 do
  3142. with UndoList^.At(Idx)^ do
  3143. begin
  3144. case action of
  3145. eaMoveCursor :
  3146. begin
  3147. { move cursor back to original position }
  3148. SetCurPtr(startpos.x,startpos.y);
  3149. end;
  3150. eaInsertText :
  3151. begin
  3152. SetCurPtr(StartPos.X,StartPos.Y);
  3153. if assigned(text) then
  3154. for Temp := 1 to length(Text^) do
  3155. DelChar;
  3156. end;
  3157. eaDeleteText :
  3158. begin
  3159. { reinsert deleted text }
  3160. SetCurPtr(EndPos.X,EndPos.Y);
  3161. if assigned(text) then
  3162. for Temp := 1 to length(Text^) do
  3163. AddChar(Text^[Temp]);
  3164. SetCurPtr(StartPos.X,StartPos.Y);
  3165. end;
  3166. eaInsertLine :
  3167. begin
  3168. SetCurPtr(EndPos.X,EndPos.Y);
  3169. SetDisplayText(EndPos.Y,Copy(GetDisplayText(EndPos.Y),EndPos.X+1,255));
  3170. BackSpace;
  3171. SetCurPtr(StartPos.X,StartPos.Y);
  3172. end;
  3173. eaDeleteLine :
  3174. begin
  3175. SetCurPtr(EndPos.X,EndPos.Y);
  3176. DelEnd;
  3177. InsertLine;
  3178. SetCurPtr(StartPos.X,StartPos.Y);
  3179. SetLineText(StartPos.Y,GetStr(Text));
  3180. end;
  3181. eaSelectionChanged :
  3182. begin
  3183. { move cursor to end of last set selection }
  3184. end;
  3185. else
  3186. { what the 'ell's an undefined action doing round 'ere mate! }
  3187. end; { once this lot is done paste into redo and modify to suit needs }
  3188. { move item to redo stack }
  3189. RedoList^.Insert(UndoList^.At(Idx));
  3190. UpdateUndoRedo(cmRedo,UndoList^.At(Idx)^.Action);
  3191. UndoList^.atDelete(Idx);
  3192. If Idx>0 then
  3193. UpdateUndoRedo(cmUndo,UndoList^.At(Idx-1)^.Action)
  3194. else
  3195. UpdateUndoRedo(cmUndo,0);
  3196. end;{Idx loop for grouped actions }
  3197. if is_grouped then
  3198. begin
  3199. Idx:=UndoList^.Count-1;
  3200. RedoList^.Insert(UndoList^.At(Idx));
  3201. UpdateUndoRedo(cmRedo,UndoList^.At(Idx)^.Action);
  3202. UndoList^.atDelete(Idx);
  3203. If Idx>0 then
  3204. UpdateUndoRedo(cmUndo,UndoList^.At(Idx-1)^.Action)
  3205. else
  3206. UpdateUndoRedo(cmUndo,0);
  3207. end;
  3208. if UndoList^.count=0 then
  3209. SetCmdState(UndoCmd,false);
  3210. SetCmdState(RedoCmd,true);
  3211. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  3212. DrawView;
  3213. end;
  3214. StoreUndo := True;
  3215. Unlock;
  3216. {$else}
  3217. NotImplemented; Exit;
  3218. {$endif Undo}
  3219. end;
  3220. procedure TCodeEditor.Redo;
  3221. {$ifdef Undo}
  3222. var
  3223. Temp,Idx,Last,Count : Longint;
  3224. Is_grouped : boolean;
  3225. {$endif Undo}
  3226. begin
  3227. {$ifdef Undo}
  3228. StoreUndo := False;
  3229. Lock;
  3230. if RedoList^.count <> 0 then
  3231. begin
  3232. Last:=RedoList^.count-1;
  3233. if RedoList^.At(Last)^.Is_grouped_action then
  3234. begin
  3235. Count:=RedoList^.At(Last)^.ActionCount;
  3236. Dec(Last);
  3237. Is_grouped:=true;
  3238. end
  3239. else
  3240. begin
  3241. Count:=1;
  3242. Is_grouped:=false;
  3243. end;
  3244. for Idx:=Last downto Last-Count+1 do
  3245. with RedoList^.At(Idx)^ do
  3246. begin
  3247. case action of
  3248. eaMoveCursor :
  3249. begin
  3250. { move cursor back to original position }
  3251. SetCurPtr(EndPos.X,EndPos.Y);
  3252. end;
  3253. eaInsertText :
  3254. begin
  3255. SetCurPtr(startpos.x,startpos.y);
  3256. InsertText(GetStr(Text));
  3257. end;
  3258. eaDeleteText :
  3259. begin
  3260. SetCurPtr(EndPos.X,EndPos.Y);
  3261. for Temp := 1 to length(GetStr(Text)) do
  3262. DelChar;
  3263. end;
  3264. eaInsertLine :
  3265. begin
  3266. SetCurPtr(StartPos.X,StartPos.Y);
  3267. InsertLine;
  3268. SetCurPtr(StartPos.X,StartPos.Y);
  3269. InsertText(GetStr(Text));
  3270. SetCurPtr(EndPos.X,EndPos.Y);
  3271. end;
  3272. eaDeleteLine :
  3273. begin
  3274. SetCurPtr(StartPos.X,StartPos.Y);
  3275. DeleteLine(StartPos.Y);
  3276. { SetCurPtr(EndPos.X,EndPos.Y);
  3277. for Temp := 1 to length(GetStr(Text)) do
  3278. DelChar;}
  3279. SetCurPtr(EndPos.X,EndPos.Y);
  3280. end;
  3281. eaSelectionChanged :
  3282. begin
  3283. { move cursor to end of last set test selection }
  3284. end;
  3285. else
  3286. { what the 'ell's an undefined action doing round 'ere mate! }
  3287. end; { once this lot is done paste back into undo and modify to suit needs }
  3288. { move item to undo stack }
  3289. UndoList^.Insert(RedoList^.At(Idx));
  3290. UpdateUndoRedo(cmUndo,RedoList^.At(Idx)^.Action);
  3291. If Idx>0 then
  3292. UpdateUndoRedo(cmRedo,RedoList^.At(Idx-1)^.Action)
  3293. else
  3294. UpdateUndoRedo(cmRedo,0);
  3295. RedoList^.atDelete(Idx);
  3296. end;{ Idx loop for grouped action }
  3297. If is_grouped then
  3298. begin
  3299. Idx:=RedoList^.count-1;
  3300. UndoList^.Insert(RedoList^.At(Idx));
  3301. UpdateUndoRedo(cmUndo,RedoList^.At(Idx)^.Action);
  3302. If Idx>0 then
  3303. UpdateUndoRedo(cmRedo,RedoList^.At(Idx-1)^.Action)
  3304. else
  3305. UpdateUndoRedo(cmRedo,0);
  3306. RedoList^.atDelete(Idx);
  3307. end;
  3308. if RedoList^.count=0 then
  3309. SetCmdState(RedoCmd,false);
  3310. SetCmdState(UndoCmd,true);
  3311. DrawView;
  3312. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  3313. end;
  3314. StoreUndo := True;
  3315. Unlock;
  3316. {$else}
  3317. NotImplemented; Exit;
  3318. {$endif Undo}
  3319. end;
  3320. procedure TCodeEditor.GotoLine;
  3321. var
  3322. GotoRec: TGotoLineDialogRec;
  3323. begin
  3324. with GotoRec do
  3325. begin
  3326. LineNo:='1';
  3327. Lines:=GetLineCount;
  3328. if EditorDialog(edGotoLine, @GotoRec) <> cmCancel then
  3329. begin
  3330. SetCurPtr(0,StrToInt(LineNo)-1);
  3331. TrackCursor(true);
  3332. end;
  3333. end;
  3334. end;
  3335. procedure TCodeEditor.Find;
  3336. var
  3337. FindRec: TFindDialogRec;
  3338. DoConf: boolean;
  3339. begin
  3340. with FindRec do
  3341. begin
  3342. Find := FindStr;
  3343. if GetCurrentWord<>'' then
  3344. Find:=GetCurrentWord;
  3345. Options := (FindFlags and ffmOptions) shr ffsOptions;
  3346. Direction := (FindFlags and ffmDirection) shr ffsDirection;
  3347. Scope := (FindFlags and ffmScope) shr ffsScope;
  3348. Origin := (FindFlags and ffmOrigin) shr ffsOrigin;
  3349. DoConf:= (FindFlags and ffPromptOnReplace)<>0;
  3350. if EditorDialog(edFind, @FindRec) <> cmCancel then
  3351. begin
  3352. FindStr := Find;
  3353. FindFlags := (Options shl ffsOptions) or (Direction shl ffsDirection) or
  3354. (Scope shl ffsScope) or (Origin shl ffsOrigin);
  3355. FindFlags := FindFlags and not ffDoReplace;
  3356. if DoConf then
  3357. FindFlags := (FindFlags or ffPromptOnReplace);
  3358. SearchRunCount:=0;
  3359. DoSearchReplace;
  3360. end;
  3361. end;
  3362. end;
  3363. procedure TCodeEditor.Replace;
  3364. var
  3365. ReplaceRec: TReplaceDialogRec;
  3366. Re: word;
  3367. begin
  3368. if IsReadOnly then Exit;
  3369. with ReplaceRec do
  3370. begin
  3371. Find := FindStr;
  3372. if GetCurrentWord<>'' then
  3373. Find:=GetCurrentWord;
  3374. Replace := ReplaceStr;
  3375. Options := (FindFlags and ffmOptions) shr ffsOptions;
  3376. Direction := (FindFlags and ffmDirection) shr ffsDirection;
  3377. Scope := (FindFlags and ffmScope) shr ffsScope;
  3378. Origin := (FindFlags and ffmOrigin) shr ffsOrigin;
  3379. Re:=EditorDialog(edReplace, @ReplaceRec);
  3380. if Re <> cmCancel then
  3381. begin
  3382. FindStr := Find;
  3383. ReplaceStr := Replace;
  3384. FindFlags := (Options shl ffsOptions) or (Direction shl ffsDirection) or
  3385. (Scope shl ffsScope) or (Origin shl ffsOrigin);
  3386. FindFlags := FindFlags or ffDoReplace;
  3387. if Re = cmYes then
  3388. FindFlags := FindFlags or ffReplaceAll;
  3389. SearchRunCount:=0;
  3390. DoSearchReplace;
  3391. end;
  3392. end;
  3393. end;
  3394. procedure TCodeEditor.DoSearchReplace;
  3395. var S: string;
  3396. DX,DY,P,Y,X: sw_integer;
  3397. Count: sw_integer;
  3398. Found,CanExit: boolean;
  3399. SForward,DoReplace,DoReplaceAll: boolean;
  3400. LeftOK,RightOK: boolean;
  3401. FoundCount: sw_integer;
  3402. A,B: TPoint;
  3403. AreaStart,AreaEnd: TPoint;
  3404. CanReplace,Confirm: boolean;
  3405. Re: word;
  3406. IFindStr : string;
  3407. BT : BTable;
  3408. function ContainsText(const SubS:string;var S: string; Start: Sw_word): Sw_integer;
  3409. var
  3410. P: Sw_Integer;
  3411. begin
  3412. if Start<=0 then
  3413. P:=0
  3414. else
  3415. begin
  3416. if SForward then
  3417. begin
  3418. if Start>length(s) then
  3419. P:=0
  3420. else if FindFlags and ffCaseSensitive<>0 then
  3421. P:=BMFScan(S[Start],length(s)+1-Start,FindStr,Bt)+1
  3422. else
  3423. P:=BMFIScan(S[Start],length(s)+1-Start,IFindStr,Bt)+1;
  3424. if P>0 then
  3425. Inc(P,Start-1);
  3426. end
  3427. else
  3428. begin
  3429. if start>length(s) then
  3430. start:=length(s);
  3431. if FindFlags and ffCaseSensitive<>0 then
  3432. P:=BMBScan(S[1],Start,FindStr,Bt)+1
  3433. else
  3434. P:=BMBIScan(S[1],Start,IFindStr,Bt)+1;
  3435. end;
  3436. end;
  3437. ContainsText:=P;
  3438. end;
  3439. function InArea(X,Y: sw_integer): boolean;
  3440. begin
  3441. InArea:=((AreaStart.Y=Y) and (AreaStart.X<=X)) or
  3442. ((AreaStart.Y<Y) and (Y<AreaEnd.Y)) or
  3443. ((AreaEnd.Y=Y) and (X<=AreaEnd.X));
  3444. end;
  3445. var CurDY: sw_integer;
  3446. begin
  3447. Inc(SearchRunCount);
  3448. SForward:=(FindFlags and ffmDirection)=ffForward;
  3449. DoReplace:=(FindFlags and ffDoReplace)<>0;
  3450. Confirm:=(FindFlags and ffPromptOnReplace)<>0;
  3451. DoReplaceAll:=(FindFlags and ffReplaceAll)<>0;
  3452. Count:=GetLineCount; FoundCount:=0;
  3453. if SForward then
  3454. DY:=1
  3455. else
  3456. DY:=-1;
  3457. DX:=DY;
  3458. if (FindFlags and ffmScope)=ffGlobal then
  3459. begin
  3460. AreaStart.X:=0;
  3461. AreaStart.Y:=0;
  3462. AreaEnd.X:=length(GetDisplayText(Count-1));
  3463. AreaEnd.Y:=Count-1;
  3464. end
  3465. else
  3466. begin
  3467. AreaStart:=SelStart;
  3468. AreaEnd:=SelEnd;
  3469. end;
  3470. X:=CurPos.X-DX;
  3471. Y:=CurPos.Y;;
  3472. if SearchRunCount=1 then
  3473. if (FindFlags and ffmOrigin)=ffEntireScope then
  3474. if SForward then
  3475. begin
  3476. X:=AreaStart.X-1;
  3477. Y:=AreaStart.Y;
  3478. end
  3479. else
  3480. begin
  3481. X:=AreaEnd.X+1;
  3482. Y:=AreaEnd.Y;
  3483. end;
  3484. if FindFlags and ffCaseSensitive<>0 then
  3485. begin
  3486. if SForward then
  3487. BMFMakeTable(FindStr,bt)
  3488. else
  3489. BMBMakeTable(FindStr,bt);
  3490. end
  3491. else
  3492. begin
  3493. IFindStr:=Upper(FindStr);
  3494. if SForward then
  3495. BMFMakeTable(IFindStr,bt)
  3496. else
  3497. BMBMakeTable(IFindStr,bt);
  3498. end;
  3499. inc(X,DX);
  3500. CanExit:=false;
  3501. if (DoReplace=false) or ((Confirm=false) and (Owner<>nil)) then
  3502. Owner^.Lock;
  3503. if InArea(X,Y) then
  3504. repeat
  3505. CurDY:=DY;
  3506. S:=GetDisplayText(Y);
  3507. P:=ContainsText(FindStr,S,X+1);
  3508. Found:=P<>0;
  3509. if Found then
  3510. begin
  3511. A.X:=P-1;
  3512. A.Y:=Y;
  3513. B.Y:=Y;
  3514. B.X:=A.X+length(FindStr);
  3515. end;
  3516. Found:=Found and InArea(A.X,A.Y);
  3517. if Found and ((FindFlags and ffWholeWordsOnly)<>0) then
  3518. begin
  3519. LeftOK:=(A.X<=0) or (not( (S[A.X] in AlphaChars) or (S[A.X] in NumberChars) ));
  3520. RightOK:=(B.X>=length(S)) or (not( (S[B.X+1] in AlphaChars) or (S[B.X+1] in NumberChars) ));
  3521. Found:=LeftOK and RightOK;
  3522. if Found=false then
  3523. begin
  3524. CurDY:=0;
  3525. X:=B.X+1;
  3526. end;
  3527. end;
  3528. if Found then
  3529. Inc(FoundCount);
  3530. if Found then
  3531. begin
  3532. Lock;
  3533. if SForward then
  3534. SetCurPtr(B.X,B.Y)
  3535. else
  3536. SetCurPtr(A.X,A.Y);
  3537. TrackCursor(true);
  3538. SetHighlight(A,B);
  3539. UnLock;
  3540. CurDY:=0;
  3541. if (DoReplace=false) then
  3542. begin
  3543. CanExit:=true;
  3544. If SForward then
  3545. begin
  3546. X:=B.X;
  3547. Y:=B.Y;
  3548. end
  3549. else
  3550. begin
  3551. X:=A.X;
  3552. Y:=A.Y;
  3553. end;
  3554. end
  3555. else
  3556. begin
  3557. if Confirm=false then CanReplace:=true else
  3558. begin
  3559. Re:=EditorDialog(edReplacePrompt,@CurPos);
  3560. case Re of
  3561. cmYes :
  3562. CanReplace:=true;
  3563. cmNo :
  3564. CanReplace:=false;
  3565. else {cmCancel}
  3566. begin
  3567. CanReplace:=false;
  3568. CanExit:=true;
  3569. end;
  3570. end;
  3571. end;
  3572. if CanReplace then
  3573. begin
  3574. Lock;
  3575. SetSelection(A,B);
  3576. DelSelect;
  3577. InsertText(ReplaceStr);
  3578. if SForward then
  3579. begin
  3580. X:=CurPos.X;
  3581. Y:=CurPos.Y;
  3582. end
  3583. else
  3584. begin
  3585. X:=A.X;
  3586. Y:=A.Y;
  3587. end;
  3588. UnLock;
  3589. end
  3590. else
  3591. begin
  3592. If SForward then
  3593. begin
  3594. X:=B.X;
  3595. Y:=B.Y;
  3596. end
  3597. else
  3598. begin
  3599. X:=A.X;
  3600. Y:=A.Y;
  3601. end;
  3602. end;
  3603. if (DoReplaceAll=false) then
  3604. CanExit:=true;
  3605. end;
  3606. end;
  3607. if (CanExit=false) and (CurDY<>0) then
  3608. begin
  3609. inc(Y,CurDY);
  3610. if SForward then
  3611. X:=0
  3612. else
  3613. X:=254;
  3614. CanExit:=(Y>=Count) or (Y<0);
  3615. end;
  3616. if not CanExit then
  3617. CanExit:=not InArea(X,Y);
  3618. until CanExit;
  3619. if (FoundCount=0) or (DoReplace) then
  3620. SetHighlight(CurPos,CurPos);
  3621. if (DoReplace=false) or ((Confirm=false) and (Owner<>nil)) then
  3622. Owner^.UnLock;
  3623. {if (DoReplace=false) or (Confirm=false) then
  3624. UnLock;}
  3625. if (FoundCount=0) then
  3626. EditorDialog(edSearchFailed,nil);
  3627. if (FindFlags and ffmScope)=ffSelectedText then
  3628. { restore selection PM }
  3629. begin
  3630. SetSelection(AreaStart,AreaEnd);
  3631. end;
  3632. end;
  3633. procedure TCodeEditor.SetInsertMode(InsertMode: boolean);
  3634. begin
  3635. if InsertMode then
  3636. Flags:=(Flags or efInsertMode)
  3637. else
  3638. Flags:=(Flags and (not efInsertMode));
  3639. DrawCursor;
  3640. end;
  3641. procedure TCodeEditor.SetModified(AModified: boolean);
  3642. begin
  3643. if AModified<>Modified then
  3644. begin
  3645. Modified:=AModified;
  3646. ModifiedChanged;
  3647. end;
  3648. end;
  3649. { there is a problem with ShiftDel here
  3650. because GetShitState tells to extend the
  3651. selection which gives wrong results (PM) }
  3652. function TCodeEditor.ShouldExtend: boolean;
  3653. var ShiftInEvent: boolean;
  3654. begin
  3655. ShiftInEvent:=false;
  3656. if Assigned(CurEvent) then
  3657. if CurEvent^.What=evKeyDown then
  3658. ShiftInEvent:=((CurEvent^.KeyShift and kbShift)<>0);
  3659. ShouldExtend:=ShiftInEvent and
  3660. not DontConsiderShiftState;
  3661. end;
  3662. procedure TCodeEditor.SetCurPtr(X,Y: sw_integer);
  3663. var OldPos,OldSEnd,OldSStart: TPoint;
  3664. Extended: boolean;
  3665. begin
  3666. Lock;
  3667. X:=Max(0,Min(MaxLineLength+1,X));
  3668. Y:=Max(0,Min(GetLineCount-1,Y));
  3669. OldPos:=CurPos;
  3670. OldSEnd:=SelEnd;
  3671. OldSStart:=SelStart;
  3672. CurPos.X:=X;
  3673. CurPos.Y:=Y;
  3674. TrackCursor(false);
  3675. if (NoSelect=false) and (ShouldExtend) then
  3676. begin
  3677. CheckSels;
  3678. Extended:=false;
  3679. if PointOfs(OldPos)=PointOfs(SelStart) then
  3680. begin SetSelection(CurPos,SelEnd); Extended:=true; end;
  3681. CheckSels;
  3682. if Extended=false then
  3683. if PointOfs(OldPos)=PointOfs(SelEnd) then
  3684. begin
  3685. if ValidBlock=false then
  3686. SetSelection(CurPos,CurPos);
  3687. SetSelection(SelStart,CurPos); Extended:=true;
  3688. end;
  3689. CheckSels;
  3690. if (Extended=false) then
  3691. if PointOfs(OldPos)<=PointOfs(CurPos)
  3692. then begin SetSelection(OldPos,CurPos); Extended:=true; end
  3693. else begin SetSelection(CurPos,OldPos); Extended:=true; end;
  3694. DrawView;
  3695. end else
  3696. if (Flags and efPersistentBlocks)=0 then
  3697. begin HideSelect; DrawView; end;
  3698. { if PointOfs(SelStart)=PointOfs(SelEnd) then
  3699. SetSelection(CurPos,CurPos);}
  3700. if (Flags and (efHighlightColumn+efHighlightRow))<>0 then
  3701. DrawView;
  3702. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and
  3703. ((Highlight.A.X<>HighLight.B.X) or (Highlight.A.Y<>HighLight.B.Y)) then
  3704. HideHighlight;
  3705. if (OldPos.Y<>CurPos.Y) and (0<=OldPos.Y) and (OldPos.Y<GetLineCount) then
  3706. SetLineText(OldPos.Y,RTrim(GetLineText(OldPos.Y),(Flags and efUseTabCharacters)=0));
  3707. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and (GetErrorMessage<>'') then
  3708. SetErrorMessage('');
  3709. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and (HighlightRow<>-1) then
  3710. SetHighlightRow(-1);
  3711. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) then
  3712. AddAction(eaMoveCursor,OldPos,CurPos,'');
  3713. if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) then
  3714. UpdateIndicator;
  3715. UnLock;
  3716. end;
  3717. procedure TCodeEditor.CheckSels;
  3718. begin
  3719. if (SelStart.Y>SelEnd.Y) or
  3720. ( (SelStart.Y=SelEnd.Y) and (SelStart.X>SelEnd.X) ) then
  3721. SetSelection(SelEnd,SelStart);
  3722. end;
  3723. procedure TCodeEditor.CodeCompleteApply;
  3724. var S: string;
  3725. I: integer;
  3726. begin
  3727. Lock;
  3728. { here should be some kind or "mark" or "break" inserted in the Undo
  3729. information, so activating it "undoes" only the completition first and
  3730. doesn't delete the complete word at once... - Gabor }
  3731. S:=GetCodeCompleteFrag;
  3732. SetCurPtr(CurPos.X-length(S),CurPos.Y);
  3733. for I:=1 to length(S) do
  3734. DelChar;
  3735. S:=GetCodeCompleteWord;
  3736. for I:=1 to length(S) do
  3737. AddChar(S[I]);
  3738. UnLock;
  3739. SetCompleteState(csInactive);
  3740. end;
  3741. procedure TCodeEditor.CodeCompleteCancel;
  3742. begin
  3743. SetCompleteState(csDenied);
  3744. end;
  3745. procedure TCodeEditor.CodeCompleteCheck;
  3746. var Line: string;
  3747. X,Y,I: sw_integer;
  3748. CurWord,NewWord: string;
  3749. begin
  3750. SetCodeCompleteFrag('');
  3751. if ((Flags and efCodeComplete)=0) or (IsReadOnly=true) then Exit;
  3752. Lock;
  3753. Line:=GetDisplayText(CurPos.Y);
  3754. X:=CurPos.X; CurWord:='';
  3755. if X<=length(Line) then
  3756. while (X>0) and (Line[X] in (NumberChars+AlphaChars)) do
  3757. begin
  3758. CurWord:=Line[X]+CurWord;
  3759. Dec(X);
  3760. end;
  3761. if (length(CurWord)>=CodeCompleteMinLen) and CompleteCodeWord(CurWord,NewWord) then
  3762. begin
  3763. SetCodeCompleteFrag(CurWord);
  3764. SetCodeCompleteWord(NewWord);
  3765. end
  3766. else
  3767. ClearCodeCompleteWord;
  3768. UnLock;
  3769. end;
  3770. function TCodeEditor.GetCodeCompleteFrag: string;
  3771. begin
  3772. GetCodeCompleteFrag:=GetStr(CodeCompleteFrag);
  3773. end;
  3774. procedure TCodeEditor.SetCodeCompleteFrag(const S: string);
  3775. begin
  3776. if Assigned(CodeCompleteFrag) then DisposeStr(CodeCompleteFrag);
  3777. CodeCompleteFrag:=NewStr(S);
  3778. end;
  3779. function TCodeEditor.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
  3780. type
  3781. TCharClass = (ccWhiteSpace,ccTab,ccAlpha,ccNumber,ccRealNumber,ccHash,ccSymbol);
  3782. var
  3783. SymbolIndex: Sw_integer;
  3784. CurrentCommentType : Byte;
  3785. FirstCC,LastCC: TCharClass;
  3786. InAsm,InComment,InSingleLineComment,InDirective,InString: boolean;
  3787. X,ClassStart: Sw_integer;
  3788. SymbolConcat: string;
  3789. LineText,Format: string;
  3790. function MatchSymbol(const What, S: string): boolean;
  3791. var Match: boolean;
  3792. begin
  3793. Match:=false;
  3794. if length(What)>=length(S) then
  3795. if copy(What,1+length(What)-length(S),length(S))=S then
  3796. Match:=true;
  3797. MatchSymbol:=Match;
  3798. end;
  3799. var MatchedSymbol: boolean;
  3800. MatchingSymbol: string;
  3801. type TPartialType = (pmNone,pmLeft,pmRight,pmAny);
  3802. function MatchesAnySpecSymbol(What: string; SClass: TSpecSymbolClass; PartialMatch: TPartialType;
  3803. CaseInsensitive: boolean): boolean;
  3804. var S: string;
  3805. I: Sw_integer;
  3806. Match,Found: boolean;
  3807. begin
  3808. Found:=false;
  3809. if CaseInsensitive then
  3810. What:=UpcaseStr(What);
  3811. if What<>'' then
  3812. for I:=1 to GetSpecSymbolCount(SClass) do
  3813. begin
  3814. SymbolIndex:=I;
  3815. S:=GetSpecSymbol(SClass,I-1);
  3816. if (length(What)<length(S)) or
  3817. ((PartialMatch=pmNone) and (length(S)<>length(What)))
  3818. then
  3819. Match:=false
  3820. else
  3821. begin
  3822. if CaseInsensitive then
  3823. S:=UpcaseStr(S);
  3824. case PartialMatch of
  3825. pmNone : Match:=What=S;
  3826. pmRight:
  3827. Match:=copy(What,length(What)-length(S)+1,length(S))=S;
  3828. else Match:=MatchSymbol(What,S);
  3829. end;
  3830. end;
  3831. if Match then
  3832. begin
  3833. MatchingSymbol:=S; Found:=true; Break;
  3834. end;
  3835. end;
  3836. MatchedSymbol:=MatchedSymbol or Found;
  3837. MatchesAnySpecSymbol:=Found;
  3838. end;
  3839. function IsCommentPrefix: boolean;
  3840. begin
  3841. IsCommentPrefix:=MatchesAnySpecSymbol(SymbolConcat,ssCommentPrefix,pmLeft,false);
  3842. end;
  3843. function IsSingleLineCommentPrefix: boolean;
  3844. begin
  3845. IsSingleLineCommentPrefix:=MatchesAnySpecSymbol(SymbolConcat,ssCommentSingleLinePrefix,pmLeft,false);
  3846. end;
  3847. function IsCommentSuffix: boolean;
  3848. begin
  3849. IsCommentSuffix:=(MatchesAnySpecSymbol(SymbolConcat,ssCommentSuffix,pmRight,false))
  3850. and (CurrentCommentType=SymbolIndex);
  3851. end;
  3852. function IsStringPrefix: boolean;
  3853. begin
  3854. IsStringPrefix:=MatchesAnySpecSymbol(SymbolConcat,ssStringPrefix,pmLeft,false);
  3855. end;
  3856. function IsStringSuffix: boolean;
  3857. begin
  3858. IsStringSuffix:=MatchesAnySpecSymbol(SymbolConcat,ssStringSuffix,pmRight,false);
  3859. end;
  3860. function IsDirectivePrefix: boolean;
  3861. begin
  3862. IsDirectivePrefix:=MatchesAnySpecSymbol(SymbolConcat,ssDirectivePrefix,pmLeft,false);
  3863. end;
  3864. function IsDirectiveSuffix: boolean;
  3865. begin
  3866. IsDirectiveSuffix:=MatchesAnySpecSymbol(SymbolConcat,ssDirectiveSuffix,pmRight,false);
  3867. end;
  3868. function IsAsmPrefix(const WordS: string): boolean;
  3869. begin
  3870. IsAsmPrefix:=MatchesAnySpecSymbol(WordS,ssAsmPrefix,pmNone,true);
  3871. end;
  3872. function IsAsmSuffix(const WordS: string): boolean;
  3873. begin
  3874. IsAsmSuffix:=MatchesAnySpecSymbol(WordS,ssAsmSuffix,pmNone,true);
  3875. end;
  3876. function GetCharClass(C: char): TCharClass;
  3877. var CC: TCharClass;
  3878. begin
  3879. if C in WhiteSpaceChars then CC:=ccWhiteSpace else
  3880. if C in TabChars then CC:=ccTab else
  3881. if C in HashChars then CC:=ccHash else
  3882. if C in AlphaChars then CC:=ccAlpha else
  3883. if C in NumberChars then CC:=ccNumber else
  3884. if (LastCC=ccNumber) and (C in RealNumberChars) then
  3885. begin
  3886. if (C='.') then
  3887. begin
  3888. if (LineText[X+1]='.') then
  3889. cc:=ccSymbol
  3890. else
  3891. CC:=ccRealNumber
  3892. end
  3893. else
  3894. cc:=ccrealnumber;
  3895. end else
  3896. CC:=ccSymbol;
  3897. GetCharClass:=CC;
  3898. end;
  3899. procedure FormatWord(SClass: TCharClass; StartX:Sw_integer;EndX: Sw_integer);
  3900. var
  3901. C: byte;
  3902. WordS: string;
  3903. begin
  3904. C:=0;
  3905. WordS:=copy(LineText,StartX,EndX-StartX+1);
  3906. if IsAsmSuffix(WordS) and (InAsm=true) and (InComment=false) and
  3907. (InString=false) and (InDirective=false) then InAsm:=false;
  3908. if InDirective then C:=coDirectiveColor else
  3909. if InComment then C:=coCommentColor else
  3910. if InString then C:=coStringColor else
  3911. if InAsm then C:=coAssemblerColor else
  3912. case SClass of
  3913. ccWhiteSpace : C:=coWhiteSpaceColor;
  3914. ccTab : C:=coTabColor;
  3915. ccNumber :
  3916. if copy(WordS,1,1)='$' then
  3917. C:=coHexNumberColor
  3918. else
  3919. C:=coNumberColor;
  3920. ccHash :
  3921. C:=coStringColor;
  3922. ccSymbol :
  3923. C:=coSymbolColor;
  3924. ccAlpha :
  3925. begin
  3926. if IsReservedWord(WordS) then
  3927. C:=coReservedWordColor
  3928. else
  3929. C:=coIdentifierColor;
  3930. end;
  3931. end;
  3932. if EndX+1>=StartX then
  3933. FillChar(Format[StartX],EndX+1-StartX,C);
  3934. if IsAsmPrefix(WordS) and
  3935. (InAsm=false) and (InComment=false) and (InDirective=false) then
  3936. InAsm:=true;
  3937. end;
  3938. procedure ProcessChar(C: char);
  3939. var CC: TCharClass;
  3940. EX: Sw_integer;
  3941. begin
  3942. CC:=GetCharClass(C);
  3943. if ClassStart=X then
  3944. FirstCC:=CC;
  3945. if ( (CC<>LastCC) and
  3946. (
  3947. ((FirstCC=ccNumber) and (CC<>ccRealNumber)) or
  3948. (((CC<>ccAlpha) or (LastCC<>ccNumber) ) and
  3949. ( (CC<>ccNumber) or (LastCC<>ccAlpha) ) and
  3950. ( (CC<>ccNumber) or (LastCC<>ccHash) ) and
  3951. ( (CC<>ccRealNumber) or (LastCC<>ccNumber))
  3952. ))) or
  3953. (X>length(LineText)) or (CC=ccSymbol) then
  3954. begin
  3955. MatchedSymbol:=false;
  3956. EX:=X-1;
  3957. if (CC=ccSymbol) then
  3958. begin
  3959. if length(SymbolConcat)>=High(SymbolConcat) then
  3960. Delete(SymbolConcat,1,1);
  3961. SymbolConcat:=SymbolConcat+C;
  3962. end;
  3963. case CC of
  3964. ccSymbol :
  3965. if IsCommentSuffix and (InComment) then
  3966. Inc(EX) else
  3967. if IsStringSuffix and (InString) then
  3968. Inc(EX) else
  3969. if IsDirectiveSuffix and (InDirective) then
  3970. Inc(EX);
  3971. end;
  3972. if (C='$') and (MatchedSymbol=false) and (IsDirectivePrefix=false) then
  3973. CC:=ccNumber;
  3974. if CC<>ccSymbol then SymbolConcat:='';
  3975. FormatWord(LastCC,ClassStart,EX);
  3976. ClassStart:=EX+1;
  3977. case CC of
  3978. ccAlpha : ;
  3979. ccNumber :
  3980. if (LastCC<>ccAlpha) then;
  3981. ccSymbol :
  3982. if IsDirectivePrefix and {(InComment=false) and }(InDirective=false) then
  3983. begin InDirective:=true; InComment:=false; Dec(ClassStart,length(MatchingSymbol)-1); end else
  3984. if IsDirectiveSuffix and (InComment=false) and (InDirective=true) then
  3985. InDirective:=false else
  3986. if IsCommentPrefix and (InComment=false) and (InString=false) then
  3987. begin
  3988. InComment:=true;
  3989. CurrentCommentType:=SymbolIndex;
  3990. InSingleLineComment:=IsSingleLineCommentPrefix;
  3991. {InString:=false; }
  3992. Dec(ClassStart,length(MatchingSymbol)-1);
  3993. end
  3994. else
  3995. if IsCommentSuffix and (InComment) then
  3996. begin InComment:=false; InString:=false; end else
  3997. if IsStringPrefix and (InComment=false) and (InString=false) then
  3998. begin InString:=true; Dec(ClassStart,length(MatchingSymbol)-1); end else
  3999. if IsStringSuffix and (InComment=false) and (InString=true) then
  4000. InString:=false;
  4001. end;
  4002. if MatchedSymbol and (InComment=false) then
  4003. SymbolConcat:='';
  4004. LastCC:=CC;
  4005. end;
  4006. end;
  4007. var CurLine: Sw_integer;
  4008. Line,NextLine,PrevLine,OldLine: PLine;
  4009. begin
  4010. if ((Flags and efSyntaxHighlight)=0) or (FromLine>=GetLineCount) then
  4011. begin
  4012. SetLineFormat(FromLine,'');
  4013. UpdateAttrs:=GetLineCount;
  4014. {$ifdef TEST_PARTIAL_SYNTAX}
  4015. LastSyntaxedLine:=GetLineCount;
  4016. SyntaxComplete:=true;
  4017. { no Idle necessary }
  4018. EventMask:=EventMask and not evIdle;
  4019. {$endif TEST_PARTIAL_SYNTAX}
  4020. UpdateIndicator;
  4021. Exit;
  4022. end;
  4023. {$ifdef TEST_PARTIAL_SYNTAX}
  4024. If ((Flags and efSyntaxHighlight)<>0) and (LastSyntaxedLine<FromLine)
  4025. and (FromLine<GetLineCount) then
  4026. CurLine:=LastSyntaxedLine
  4027. else
  4028. {$endif TEST_PARTIAL_SYNTAX}
  4029. CurLine:=FromLine;
  4030. if CurLine>0 then PrevLine:=Lines^.At(CurLine-1) else PrevLine:=nil;
  4031. repeat
  4032. Line:=Lines^.At(CurLine);
  4033. InSingleLineComment:=false;
  4034. if PrevLine<>nil then
  4035. begin
  4036. InAsm:=PrevLine^.EndsWithAsm;
  4037. InComment:=PrevLine^.EndsWithComment and not PrevLine^.EndsInSingleLineComment;
  4038. CurrentCommentType:=PrevLine^.EndCommentType;
  4039. InDirective:=PrevLine^.EndsWithDirective;
  4040. end
  4041. else
  4042. begin
  4043. InAsm:=false;
  4044. InComment:=false;
  4045. CurrentCommentType:=0;
  4046. InDirective:=false;
  4047. end;
  4048. OldLine:=Line;
  4049. Line^.BeginsWithAsm:=InAsm;
  4050. Line^.BeginsWithComment:=InComment;
  4051. Line^.BeginsWithDirective:=InDirective;
  4052. Line^.BeginCommentType:=CurrentCommentType;
  4053. LineText:=GetLineText(CurLine);
  4054. Format:=CharStr(chr(coTextColor),length(LineText));
  4055. LastCC:=ccWhiteSpace;
  4056. ClassStart:=1;
  4057. SymbolConcat:='';
  4058. InString:=false;
  4059. if LineText<>'' then
  4060. begin
  4061. for X:=1 to length(LineText) do
  4062. ProcessChar(LineText[X]);
  4063. Inc(X);
  4064. ProcessChar(' ');
  4065. end;
  4066. SetLineFormat(CurLine,Format);
  4067. Line^.EndsWithAsm:=InAsm;
  4068. Line^.EndsWithComment:=InComment;
  4069. Line^.EndsInSingleLineComment:=InSingleLineComment;
  4070. Line^.EndCommentType:=CurrentCommentType;
  4071. Line^.EndsWithDirective:=InDirective;
  4072. Inc(CurLine);
  4073. if CurLine>=GetLineCount then
  4074. Break;
  4075. NextLine:=Lines^.At(CurLine);
  4076. if ((Attrs and attrForceFull)=0) then
  4077. if { Why should we go
  4078. (InAsm=false) and (NextLine^.BeginsWithAsm=false) and
  4079. (InComment=false) and (NextLine^.BeginsWithComment=false) and
  4080. (InDirective=false) and (NextLine^.BeginsWithDirective=false) and
  4081. OldLine = Line so this is nonsense
  4082. (OldLine^.EndsWithComment=Line^.EndsWithComment) and
  4083. (OldLine^.EndsWithAsm=Line^.EndsWithAsm) and
  4084. (OldLine^.EndsWithDirective=Line^.EndsWithDirective) and }
  4085. {$ifdef TEST_PARTIAL_SYNTAX}
  4086. (CurLine>FromLine) and
  4087. {$endif TEST_PARTIAL_SYNTAX}
  4088. (NextLine^.BeginsWithAsm=Line^.EndsWithAsm) and
  4089. (NextLine^.BeginsWithComment=Line^.EndsWithComment) and
  4090. (NextLine^.BeginsWithDirective=Line^.EndsWithDirective) and
  4091. (NextLine^.BeginCommentType=Line^.EndCommentType) and
  4092. (NextLine^.Format<>nil) then
  4093. Break;
  4094. {$ifdef TEST_PARTIAL_SYNTAX}
  4095. if (CurLine<GetLineCount) and
  4096. (CurLine>FromLine) and
  4097. ((Attrs and attrForceFull)=0) and
  4098. (CurLine>Delta.Y+Size.Y) then
  4099. begin
  4100. If SyntaxComplete then
  4101. begin
  4102. SyntaxComplete:=false;
  4103. { no Idle necessary }
  4104. EventMask:=EventMask or evIdle;
  4105. UpdateIndicator;
  4106. end;
  4107. LastSyntaxedLine:=CurLine-1;
  4108. break;
  4109. end;
  4110. {$endif TEST_PARTIAL_SYNTAX}
  4111. PrevLine:=Line;
  4112. until false;
  4113. UpdateAttrs:=CurLine;
  4114. {$ifdef TEST_PARTIAL_SYNTAX}
  4115. If LastSyntaxedLine<CurLine-1 then
  4116. LastSyntaxedLine:=CurLine-1;
  4117. if CurLine=GetLineCount then
  4118. begin
  4119. SyntaxComplete:=true;
  4120. { no Idle necessary }
  4121. EventMask:=EventMask and not evIdle;
  4122. UpdateIndicator;
  4123. end;
  4124. {$endif TEST_PARTIAL_SYNTAX}
  4125. end;
  4126. function TCodeEditor.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
  4127. var Line: Sw_integer;
  4128. begin
  4129. Lock;
  4130. Line:=FromLine;
  4131. repeat
  4132. Line:=UpdateAttrs(Line,Attrs);
  4133. until (Line>=GetLineCount) or (Line>ToLine);
  4134. UpdateAttrsRange:=Line;
  4135. Unlock;
  4136. end;
  4137. procedure TCodeEditor.DrawLines(FirstLine: sw_integer);
  4138. begin
  4139. if FirstLine>=(Delta.Y+Size.Y) then Exit; { falls outside of the screen }
  4140. DrawView;
  4141. end;
  4142. function TCodeEditor.InsertText(const S: string): Boolean;
  4143. var I: sw_integer;
  4144. OldPos: TPoint;
  4145. HoldUndo : boolean;
  4146. begin
  4147. Lock;
  4148. OldPos:=CurPos;
  4149. HoldUndo:=StoreUndo;
  4150. StoreUndo:=false;
  4151. for I:=1 to length(S) do
  4152. AddChar(S[I]);
  4153. InsertText:=true;
  4154. StoreUndo:=HoldUndo;
  4155. AddAction(eaInsertText,OldPos,CurPos,S);
  4156. UnLock;
  4157. end;
  4158. function TCodeEditor.InsertFrom(Editor: PCodeEditor): Boolean;
  4159. var OK: boolean;
  4160. LineDelta,LineCount: Sw_integer;
  4161. StartPos,DestPos,BPos,EPos: TPoint;
  4162. LineStartX,LineEndX: Sw_integer;
  4163. S,OrigS,AfterS: string;
  4164. VerticalBlock: boolean;
  4165. SEnd: TPoint;
  4166. begin
  4167. if (Editor^.Flags and efVerticalBlocks)<>0 then
  4168. begin
  4169. NotImplemented;
  4170. Exit;
  4171. end;
  4172. Lock;
  4173. OK:=(Editor^.SelStart.X<>Editor^.SelEnd.X) or (Editor^.SelStart.Y<>Editor^.SelEnd.Y);
  4174. if OK then
  4175. begin
  4176. StartPos:=CurPos; DestPos:=CurPos;
  4177. EPos:=CurPos;
  4178. VerticalBlock:=(Editor^.Flags and efVerticalBlocks)<>0;
  4179. LineDelta:=0; LineCount:=(Editor^.SelEnd.Y-Editor^.SelStart.Y)+1;
  4180. OK:=GetLineCount<MaxLineCount;
  4181. OrigS:=GetDisplayText(DestPos.Y);
  4182. AfterS:=Copy(OrigS,DestPos.X+1,255);
  4183. while OK and (LineDelta<LineCount) do
  4184. begin
  4185. if (LineDelta>0) and (VerticalBlock=false) then
  4186. begin
  4187. Lines^.AtInsert(DestPos.Y,NewLine(''));
  4188. BPos.X:=0;BPos.Y:=DestPos.Y;
  4189. EPOS.X:=0;EPos.Y:=DestPos.Y;
  4190. AddAction(eaInsertLine,BPos,EPos,'');
  4191. LimitsChanged;
  4192. end;
  4193. if (LineDelta=0) or VerticalBlock then
  4194. LineStartX:=Editor^.SelStart.X
  4195. else
  4196. LineStartX:=0;
  4197. if (LineDelta=LineCount-1) or VerticalBlock then
  4198. LineEndX:=Editor^.SelEnd.X-1
  4199. else
  4200. LineEndX:=255;
  4201. if LineEndX<LineStartX then
  4202. S:=''
  4203. else if VerticalBlock then
  4204. S:=RExpand(copy(Editor^.GetLineText(Editor^.SelStart.Y+LineDelta),LineStartX+1,LineEndX-LineStartX+1),
  4205. Min(LineEndX-LineStartX+1,255))
  4206. else
  4207. S:=copy(Editor^.GetLineText(Editor^.SelStart.Y+LineDelta),LineStartX+1,LineEndX-LineStartX+1);
  4208. if VerticalBlock=false then
  4209. begin
  4210. If LineDelta>0 then
  4211. OrigS:='';
  4212. if LineDelta=LineCount-1 then
  4213. begin
  4214. SetLineText(DestPos.Y,RExpand(copy(OrigS,1,DestPos.X),DestPos.X)+S+AfterS);
  4215. BPos.X:=DestPos.X;BPos.Y:=DestPos.Y;
  4216. EPOS.X:=DestPos.X+Length(S);EPos.Y:=DestPos.Y;
  4217. AddAction(eaInsertText,BPos,EPos,S);
  4218. end
  4219. else
  4220. begin
  4221. SetLineText(DestPos.Y,RExpand(copy(OrigS,1,DestPos.X),DestPos.X)+S);
  4222. BPos.X:=DestPos.X;BPos.Y:=DestPos.Y;
  4223. EPOS.X:=DestPos.X+Length(S);EPos.Y:=DestPos.Y;
  4224. AddAction(eaInsertText,BPos,EPos,S);
  4225. end;
  4226. if LineDelta=LineCount-1 then
  4227. begin
  4228. SEnd.Y:=DestPos.Y;
  4229. SEnd.X:=DestPos.X+length(S);
  4230. end
  4231. else
  4232. begin
  4233. Inc(DestPos.Y);
  4234. DestPos.X:=0;
  4235. end;
  4236. end
  4237. else { if VerticalBlock=false then .. else }
  4238. begin
  4239. { this is not yet implemented !! PM }
  4240. S:=RExpand(S,LineEndX-LineStartX+1);
  4241. end;
  4242. Inc(LineDelta);
  4243. OK:=GetLineCount<MaxLineCount;
  4244. end;
  4245. if OK=false then EditorDialog(edTooManyLines,nil);
  4246. { mainly to force eaMove insertion }
  4247. if not IsClipboard then
  4248. SetCurPtr(EPos.X,EPos.Y);
  4249. SetCurPtr(StartPos.X,StartPos.Y);
  4250. UpdateAttrs(StartPos.Y,attrAll);
  4251. SetModified(true);
  4252. LimitsChanged;
  4253. SetSelection(CurPos,SEnd);
  4254. if IsClipboard then
  4255. begin
  4256. Inc(DestPos.X,length(S));
  4257. SetCurPtr(DestPos.X,DestPos.Y);
  4258. end;
  4259. DrawView;
  4260. end;
  4261. UnLock;
  4262. InsertFrom:=OK;
  4263. end;
  4264. function TCodeEditor.IsClipboard: Boolean;
  4265. begin
  4266. IsClipboard:=(Clipboard=@Self);
  4267. end;
  4268. procedure TCodeEditor.HideHighlight;
  4269. begin
  4270. SetHighlight(CurPos,CurPos);
  4271. end;
  4272. procedure TCodeEditor.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string);
  4273. {$ifdef Undo}
  4274. var
  4275. ActionIntegrated : boolean;
  4276. pa : PEditorAction;
  4277. S : String;
  4278. {$endif Undo}
  4279. begin
  4280. {$ifdef Undo}
  4281. if (UndoList=nil) or (not StoreUndo) then Exit;
  4282. ActionIntegrated:=false;
  4283. if UndoList^.count>0 then
  4284. begin
  4285. pa:=UndoList^.At(UndoList^.count-1);
  4286. if (pa^.action=AAction) and
  4287. (pa^.EndPos.X=AStartPos.X) and
  4288. (pa^.EndPos.Y=AStartPos.Y) and
  4289. { do not group InsertLine and DeleteLine !! }
  4290. ((AAction=eaMoveCursor) or
  4291. (AAction=eaInsertText) or
  4292. (AAction=eaDeleteText))
  4293. then
  4294. begin
  4295. pa^.EndPos:=AEndPos;
  4296. S:=GetStr(pa^.text);
  4297. if S<>'' then
  4298. DisposeStr(pa^.text);
  4299. if (AAction=eaDeleteText) and
  4300. (AStartPos.X>AEndPos.X) then
  4301. pa^.text:=NewStr(AText+S)
  4302. else
  4303. pa^.text:=NewStr(S+AText);
  4304. ActionIntegrated:=true;
  4305. end;
  4306. end;
  4307. if not ActionIntegrated then
  4308. begin
  4309. UndoList^.Insert(New(PEditorAction,Init(AAction,AStartPos,AEndPos,AText)));
  4310. if assigned(UndoList^.CurrentGroupedAction) then
  4311. Inc(UndoList^.CurrentGroupedAction^.actionCount);
  4312. UpdateUndoRedo(cmUndo,AAction);
  4313. end;
  4314. if UndoList^.count>0 then
  4315. begin
  4316. SetCmdState(UndoCmd,true);
  4317. SetCmdState(RedoCmd,false);
  4318. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  4319. UpdateUndoRedo(cmRedo,0);
  4320. RedoList^.FreeAll;
  4321. end;
  4322. {$endif Undo}
  4323. end;
  4324. procedure TCodeEditor.AddGroupedAction(AAction : byte);
  4325. begin
  4326. {$ifdef Undo}
  4327. UndoList^.CurrentGroupedAction:=New(PEditorAction,Init_group(AAction));
  4328. {$endif Undo}
  4329. end;
  4330. procedure TCodeEditor.CloseGroupedAction(AAction : byte);
  4331. begin
  4332. {$ifdef Undo}
  4333. UndoList^.Insert(UndoList^.CurrentGroupedAction);
  4334. UndoList^.CurrentGroupedAction:=nil;
  4335. UpdateUndoRedo(cmUndo,AAction);
  4336. {$endif Undo}
  4337. end;
  4338. function TCodeEditor.ValidBlock: boolean;
  4339. begin
  4340. ValidBlock:=(SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y);
  4341. end;
  4342. procedure TCodeEditor.SetSelection(A, B: TPoint);
  4343. var WV: boolean;
  4344. OS,OE: TPoint;
  4345. begin
  4346. WV:=ValidBlock;
  4347. OS:=SelStart; OE:=SelEnd;
  4348. SelStart:=A; SelEnd:=B;
  4349. if (WV=false) and (ValidBlock=false) then { do nothing } else
  4350. if (OS.X<>SelStart.X) or (OS.Y<>SelStart.Y) or
  4351. (OE.X<>SelEnd.X) or (OE.Y<>SelEnd.Y) then
  4352. SelectionChanged;
  4353. end;
  4354. procedure TCodeEditor.SetHighlight(A, B: TPoint);
  4355. begin
  4356. Highlight.A:=A; Highlight.B:=B;
  4357. HighlightChanged;
  4358. end;
  4359. procedure TCodeEditor.SetHighlightRow(Row: sw_integer);
  4360. begin
  4361. HighlightRow:=Row;
  4362. DrawView;
  4363. end;
  4364. procedure TCodeEditor.SetDebuggerRow(Row: sw_integer);
  4365. begin
  4366. DebuggerRow:=Row;
  4367. DrawView;
  4368. end;
  4369. procedure TCodeEditor.SetCompleteState(AState: TCompleteState);
  4370. begin
  4371. if AState<>CompleteState then
  4372. begin
  4373. CompleteState:=AState;
  4374. if CompleteState<>csOffering then
  4375. ClearCodeCompleteWord;
  4376. end;
  4377. end;
  4378. procedure TCodeEditor.SelectAll(Enable: boolean);
  4379. var A,B: TPoint;
  4380. begin
  4381. if (Enable=false) or (GetLineCount=0) then
  4382. begin A:=CurPos; B:=CurPos end
  4383. else
  4384. begin
  4385. A.X:=0; A.Y:=0;
  4386. { B.Y:=GetLineCount-1;
  4387. B.X:=length(GetLineText(B.Y));}
  4388. B.Y:=GetLineCount; B.X:=0;
  4389. end;
  4390. SetSelection(A,B);
  4391. DrawView;
  4392. end;
  4393. procedure TCodeEditor.SelectionChanged;
  4394. var Enable,CanPaste: boolean;
  4395. begin
  4396. if GetLineCount=0 then
  4397. begin
  4398. SelStart.X:=0; SelStart.Y:=0; SelEnd:=SelStart;
  4399. end
  4400. else
  4401. if SelEnd.Y>GetLineCount-1 then
  4402. if (SelEnd.Y<>GetLineCount) or (SelEnd.X<>0) then
  4403. begin
  4404. SelEnd.Y:=GetLineCount-1;
  4405. SelEnd.X:=length(GetDisplayText(SelEnd.Y));
  4406. end;
  4407. Enable:=((SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y)) and (Clipboard<>nil);
  4408. SetCmdState(ToClipCmds,Enable and (Clipboard<>@Self));
  4409. SetCmdState(NulClipCmds,Enable);
  4410. CanPaste:=(Clipboard<>nil) and ((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
  4411. (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
  4412. SetCmdState(FromClipCmds,CanPaste and (Clipboard<>@Self));
  4413. {$ifdef WinClipSupported}
  4414. SetCmdState(FromWinClipCmds,GetTextWinClipboardSize>0);
  4415. {$endif WinClipSupported}
  4416. SetCmdState(UndoCmd,(UndoList^.count>0));
  4417. SetCmdState(RedoCmd,(RedoList^.count>0));
  4418. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  4419. DrawView;
  4420. end;
  4421. procedure TCodeEditor.HighlightChanged;
  4422. begin
  4423. DrawView;
  4424. end;
  4425. procedure TCodeEditor.ModifiedChanged;
  4426. begin
  4427. UpdateIndicator;
  4428. end;
  4429. procedure TCodeEditor.SetState(AState: Word; Enable: Boolean);
  4430. begin
  4431. inherited SetState(AState,Enable);
  4432. if (AState and (sfActive+sfSelected+sfFocused))<>0 then
  4433. begin
  4434. SelectionChanged;
  4435. if ((State and sfFocused)=0) and (CompleteState=csOffering) then
  4436. ClearCodeCompleteWord;
  4437. end;
  4438. end;
  4439. function TCodeEditor.GetPalette: PPalette;
  4440. const P: string[length(CEditor)] = CEditor;
  4441. begin
  4442. GetPalette:=@P;
  4443. end;
  4444. constructor TCodeEditor.Load(var S: TStream);
  4445. var TS: PSubStream;
  4446. TSize: longint;
  4447. begin
  4448. inherited Load(S);
  4449. New(UndoList,init(500,1000));
  4450. New(RedoList,init(500,1000));
  4451. New(Lines, Init(500,1000));
  4452. { we have always need at least 1 line }
  4453. Lines^.Insert(NewLine(''));
  4454. GetPeerViewPtr(S,Indicator);
  4455. S.Read(Flags,SizeOf(Flags));
  4456. S.Read(TabSize,SizeOf(TabSize));
  4457. if (Flags and efStoreContent)<>0 then
  4458. begin
  4459. S.Read(TSize,SizeOf(TSize));
  4460. New(TS, Init(@S,S.GetPos,TSize));
  4461. {$ifdef TEST_PARTIAL_SYNTAX}
  4462. SyntaxComplete:=false;
  4463. { Idle necessary }
  4464. EventMask:=EventMask or evIdle;
  4465. {$endif TEST_PARTIAL_SYNTAX}
  4466. LoadFromStream(TS);
  4467. Dispose(TS, Done);
  4468. end;
  4469. S.Read(SelStart,SizeOf(SelStart));
  4470. S.Read(SelEnd,SizeOf(SelEnd));
  4471. S.Read(Highlight,SizeOf(Highlight));
  4472. S.Read(CurPos,SizeOf(CurPos));
  4473. S.Read(StoreUndo,SizeOf(StoreUndo));
  4474. S.Read(IsReadOnly,SizeOf(IsReadOnly));
  4475. S.Read(NoSelect,SizeOf(NoSelect));
  4476. S.Read(HighlightRow,SizeOf(HighlightRow));
  4477. SetDebuggerRow(-1);
  4478. LimitsChanged;
  4479. SelectionChanged; HighlightChanged;
  4480. UpdateIndicator;
  4481. end;
  4482. procedure TCodeEditor.Store(var S: TStream);
  4483. var {NS: TNulStream;}
  4484. TSizePos,TSize,EndPos: longint;
  4485. begin
  4486. inherited Store(S);
  4487. PutPeerViewPtr(S,Indicator);
  4488. S.Write(Flags,SizeOf(Flags));
  4489. S.Write(TabSize,SizeOf(TabSize));
  4490. if (Flags and efStoreContent)<>0 then
  4491. begin
  4492. { NS.Init;
  4493. SaveToStream(@NS);
  4494. TSize:=NS.GetSize;
  4495. NS.Done;
  4496. This is waste of time PM
  4497. use Seek instead !! }
  4498. TSize:=0;
  4499. TSizePos:=S.GetPos;
  4500. S.Write(TSize,SizeOf(TSize));
  4501. SaveToStream(@S);
  4502. EndPos:=S.GetPos;
  4503. TSize:=EndPos-TSizePos-SizeOf(TSize);
  4504. S.Seek(TSizePos);
  4505. S.Write(TSize,SizeOf(TSize));
  4506. S.Seek(EndPos);
  4507. end;
  4508. S.Write(SelStart,SizeOf(SelStart));
  4509. S.Write(SelEnd,SizeOf(SelEnd));
  4510. S.Write(Highlight,SizeOf(Highlight));
  4511. S.Write(CurPos,SizeOf(CurPos));
  4512. S.Write(StoreUndo,SizeOf(StoreUndo));
  4513. S.Write(IsReadOnly,SizeOf(IsReadOnly));
  4514. S.Write(NoSelect,SizeOf(NoSelect));
  4515. S.Write(HighlightRow,SizeOf(HighlightRow));
  4516. end;
  4517. function TCodeEditor.LoadFromStream(Stream: PStream): boolean;
  4518. var S: string;
  4519. AllLinesComplete,LineComplete,OK: boolean;
  4520. begin
  4521. DeleteAllLines;
  4522. ChangedLine:=-1;
  4523. AllLinesComplete:=true;
  4524. OK:=(Stream^.Status=stOK);
  4525. if eofstream(Stream) then
  4526. AddLine('')
  4527. else
  4528. while OK and (eofstream(Stream)=false) and (GetLineCount<MaxLineCount) do
  4529. begin
  4530. ReadlnFromStream(Stream,S,LineComplete);
  4531. AllLinesComplete:=AllLinesComplete and LineComplete;
  4532. OK:=OK and (Stream^.Status=stOK);
  4533. if OK then AddLine(S);
  4534. if not LineComplete and (ChangedLine=-1) then
  4535. ChangedLine:=GetLineCount;
  4536. end;
  4537. LimitsChanged;
  4538. if not AllLinesComplete then
  4539. SetModified(true);
  4540. if (Flags and efSyntaxHighlight)<>0 then
  4541. UpdateAttrsRange(0,Min(Delta.Y+Size.Y,GetLineCount-1),
  4542. attrAll
  4543. {$ifndef TEST_PARTIAL_SYNTAX}
  4544. +attrForceFull
  4545. {$endif TEST_PARTIAL_SYNTAX}
  4546. );
  4547. TextStart;
  4548. LoadFromStream:=OK;
  4549. end;
  4550. function TCodeEditor.SaveToStream(Stream: PStream): boolean;
  4551. var A,B: TPoint;
  4552. begin
  4553. A.Y:=0; A.X:=0;
  4554. B.Y:=GetLineCount-1;
  4555. if GetLineCount>0 then
  4556. B.X:=length(GetDisplayText(B.Y))
  4557. else
  4558. B.X:=0;
  4559. SaveToStream:=SaveAreaToStream(Stream,A,B);
  4560. end;
  4561. function TCodeEditor.SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
  4562. var S: string;
  4563. OK: boolean;
  4564. Line: Sw_integer;
  4565. P: PLine;
  4566. begin
  4567. if EndP.X=0 then
  4568. begin
  4569. if EndP.Y>0 then
  4570. begin
  4571. EndP.X:=length(GetDisplayText(EndP.Y));
  4572. end
  4573. else
  4574. EndP.X:=0;
  4575. end
  4576. else
  4577. Dec(EndP.X);
  4578. OK:=(Stream^.Status=stOK); Line:=StartP.Y;
  4579. while OK and (Line<=EndP.Y) and (Line<GetLineCount) do
  4580. begin
  4581. P:=Lines^.At(Line);
  4582. if P^.Text=nil then S:='' else
  4583. begin
  4584. S:=P^.Text^;
  4585. if Line=EndP.Y then S:=copy(S,1,LinePosToCharIdx(Line,EndP.X));
  4586. if Line=StartP.Y then S:=copy(S,LinePosToCharIdx(Line,StartP.X),255);
  4587. end;
  4588. { Remove all traling spaces PM }
  4589. if (Flags and efKeepTrailingSpaces)=0 then
  4590. While (Length(S)>0) and (S[Length(S)]=' ') do
  4591. Dec(S[0]);
  4592. { if (Flags and efUseTabCharacters)<>0 then
  4593. S:=CompressUsingTabs(S,TabSize);
  4594. }
  4595. Stream^.Write(S[1],length(S));
  4596. if Line<EndP.Y then
  4597. Stream^.Write(EOL[1],length(EOL));
  4598. Inc(Line);
  4599. OK:=OK and (Stream^.Status=stOK);
  4600. end;
  4601. SaveAreaToStream:=OK;
  4602. end;
  4603. destructor TCodeEditor.Done;
  4604. begin
  4605. inherited Done;
  4606. if assigned(Lines) then
  4607. Dispose(Lines, Done);
  4608. If assigned(RedoList) then
  4609. Dispose(RedoList,done);
  4610. If assigned(UndoList) then
  4611. Dispose(UndoList,done);
  4612. if Assigned(CodeCompleteFrag) then
  4613. DisposeStr(CodeCompleteFrag);
  4614. if Assigned(CodeCompleteWord) then
  4615. DisposeStr(CodeCompleteWord);
  4616. end;
  4617. {$ifdef Undo}
  4618. constructor TEditorAction.init(act:byte; StartP,EndP:TPoint;Txt:String);
  4619. begin
  4620. Action:=act;
  4621. StartPos:=StartP;
  4622. EndPos:=EndP;
  4623. Text:=NewStr(txt);
  4624. ActionCount:=0;
  4625. end;
  4626. constructor TEditorAction.init_group(act:byte);
  4627. begin
  4628. Action:=act;
  4629. ActionCount:=0;
  4630. end;
  4631. function TEditorAction.Is_grouped_action : boolean;
  4632. begin
  4633. Is_grouped_action:=Action in [eaCut,eaPaste,eaPasteWin,eaClear];
  4634. end;
  4635. destructor TEditorAction.done;
  4636. begin
  4637. DisposeStr(Text);
  4638. end;
  4639. {$else}
  4640. procedure TEditorActionCollection.FreeItem(Item: Pointer);
  4641. begin
  4642. if assigned(Item) then
  4643. freemem(Item,Sizeof(TEditorAction));
  4644. end;
  4645. {$endif Undo}
  4646. function TEditorActionCollection.At(Idx : sw_integer) : PEditorAction;
  4647. begin
  4648. At:=PEditorAction(Inherited At(Idx));
  4649. end;
  4650. constructor TFileEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  4651. PScrollBar; AIndicator: PIndicator;const AFileName: string);
  4652. begin
  4653. inherited Init(Bounds,AHScrollBAr,AVScrollBAr,AIndicator,0);
  4654. FileName:=AFileName;
  4655. UpdateIndicator;
  4656. Message(@Self,evBroadcast,cmFileNameChanged,@Self);
  4657. OnDiskLoadTime:=-1;
  4658. end;
  4659. function TFileEditor.LoadFile: boolean;
  4660. var S: PBufStream;
  4661. OK: boolean;
  4662. begin
  4663. New(S, Init(GetShortName(FileName),stOpenRead,EditorTextBufSize));
  4664. OK:=Assigned(S);
  4665. {$ifdef TEST_PARTIAL_SYNTAX}
  4666. SyntaxComplete:=false;
  4667. { Idle necessary }
  4668. EventMask:=EventMask or evIdle;
  4669. {$endif TEST_PARTIAL_SYNTAX}
  4670. if OK then OK:=LoadFromStream(S);
  4671. if Assigned(S) then Dispose(S, Done);
  4672. OnDiskLoadTime:=GetFileTime(FileName);
  4673. LoadFile:=OK;
  4674. end;
  4675. function TFileEditor.IsChangedOnDisk : boolean;
  4676. begin
  4677. IsChangedOnDisk:=(OnDiskLoadTime<>GetFileTime(FileName)) and (OnDiskLoadTime<>-1);
  4678. end;
  4679. function TFileEditor.SaveFile: boolean;
  4680. var OK: boolean;
  4681. BAKName: string;
  4682. S: PBufStream;
  4683. f: text;
  4684. begin
  4685. If IsChangedOnDisk then
  4686. begin
  4687. if EditorDialog(edFileOnDiskChanged, @FileName) <> cmYes then
  4688. begin
  4689. SaveFile:=false;
  4690. exit;
  4691. end;
  4692. end;
  4693. {$I-}
  4694. if (Flags and efBackupFiles)<>0 then
  4695. begin
  4696. BAKName:=DirAndNameOf(FileName)+'.bak';
  4697. Assign(f,BAKName);
  4698. Erase(f);
  4699. EatIO;
  4700. Assign(f,FileName);
  4701. Rename(F,BAKName);
  4702. EatIO;
  4703. end;
  4704. {$I+}
  4705. New(S, Init(FileName,stCreate,EditorTextBufSize));
  4706. OK:=Assigned(S);
  4707. if OK then OK:=SaveToStream(S);
  4708. if Assigned(S) then Dispose(S, Done);
  4709. if OK then SetModified(false);
  4710. { don't forget to update the OnDiskLoadTime value }
  4711. OnDiskLoadTime:=GetFileTime(FileName);
  4712. SaveFile:=OK;
  4713. end;
  4714. function TFileEditor.ShouldSave: boolean;
  4715. begin
  4716. ShouldSave:=Modified{ or (FileName='')};
  4717. end;
  4718. function TFileEditor.Save: Boolean;
  4719. begin
  4720. if ShouldSave=false then begin Save:=true; Exit; end;
  4721. if FileName = '' then Save := SaveAs else Save := SaveFile;
  4722. end;
  4723. function TFileEditor.SaveAs: Boolean;
  4724. begin
  4725. SaveAs := False;
  4726. if EditorDialog(edSaveAs, @FileName) <> cmCancel then
  4727. begin
  4728. FileName := FExpand(FileName);
  4729. Message(Owner, evBroadcast, cmUpdateTitle, @Self);
  4730. { if we rename the file the OnDiskLoadTime is wrong so we reset it }
  4731. OnDiskLoadTime:=-1;
  4732. SaveAs := SaveFile;
  4733. if IsClipboard then FileName := '';
  4734. Message(Application,evBroadcast,cmFileNameChanged,@Self);
  4735. end;
  4736. end;
  4737. function TFileEditor.SaveAsk: boolean;
  4738. var OK: boolean;
  4739. D: Sw_integer;
  4740. begin
  4741. OK:=Modified=false;
  4742. if OK=false then
  4743. begin
  4744. if FileName = '' then D := edSaveUntitled else D := edSaveModify;
  4745. case EditorDialog(D, @FileName) of
  4746. cmYes : OK := Save;
  4747. cmNo : begin Modified := False; OK:=true; end;
  4748. cmCancel : begin
  4749. OK := False;
  4750. Message(Application,evBroadcast,cmSaveCancelled,@Self);
  4751. end;
  4752. end;
  4753. end;
  4754. SaveAsk:=OK;
  4755. end;
  4756. procedure TFileEditor.HandleEvent(var Event: TEvent);
  4757. var SH,B: boolean;
  4758. begin
  4759. case Event.What of
  4760. evBroadcast :
  4761. case Event.Command of
  4762. cmFileNameChanged :
  4763. if (Event.InfoPtr=nil) or (Event.InfoPtr=@Self) then
  4764. begin
  4765. B:=(Flags and efSyntaxHighlight)<>0;
  4766. SH:=UseSyntaxHighlight(@Self);
  4767. if SH<>B then
  4768. if SH then
  4769. SetFlags(Flags or efSyntaxHighlight)
  4770. else
  4771. SetFlags(Flags and not efSyntaxHighlight);
  4772. if UseTabsPattern(@Self) then
  4773. SetFlags(Flags or efUseTabCharacters);
  4774. end;
  4775. end;
  4776. end;
  4777. inherited HandleEvent(Event);
  4778. end;
  4779. function TFileEditor.Valid(Command: Word): Boolean;
  4780. var OK: boolean;
  4781. begin
  4782. OK:=inherited Valid(Command);
  4783. if OK and ((Command=cmClose) or (Command=cmQuit)) then
  4784. if IsClipboard=false then
  4785. OK:=SaveAsk;
  4786. Valid:=OK;
  4787. end;
  4788. constructor TFileEditor.Load(var S: TStream);
  4789. var P: PString;
  4790. SSP,SEP,CP,DP: TPoint;
  4791. HR: TRect;
  4792. PA : Array[1..2] of pointer;
  4793. HoldUndo : boolean;
  4794. begin
  4795. inherited Load(S);
  4796. HoldUndo:=StoreUndo;
  4797. StoreUndo:=False;
  4798. P:=S.ReadStr;
  4799. FileName:=GetStr(P);
  4800. if P<>nil then DisposeStr(P);
  4801. UpdateIndicator;
  4802. { Message(@Self,evBroadcast,cmFileNameChanged,@Self);}
  4803. SSP:=SelStart; SEP:=SelEnd;
  4804. CP:=CurPos;
  4805. HR:=Highlight;
  4806. DP:=Delta;
  4807. if FileName<>'' then
  4808. LoadFile;
  4809. if Modified then
  4810. begin
  4811. PA[1]:=@FileName;
  4812. longint(PA[2]):=ChangedLine;
  4813. EditorDialog(edChangedOnloading,@PA);
  4814. end;
  4815. SetHighlight(HR.A,HR.B);
  4816. SetSelection(SSP,SEP);
  4817. SetCurPtr(CP.X,CP.Y);
  4818. ScrollTo(DP.X,DP.Y);
  4819. SetModified(false);
  4820. LimitsChanged;
  4821. StoreUndo:=HoldUndo;
  4822. end;
  4823. procedure TFileEditor.Store(var S: TStream);
  4824. begin
  4825. inherited Store(S);
  4826. S.WriteStr(@FileName);
  4827. end;
  4828. function CreateFindDialog: PDialog;
  4829. var R,R1,R2: TRect;
  4830. D: PDialog;
  4831. IL1: PInputLine;
  4832. Control : PView;
  4833. CB1: PCheckBoxes;
  4834. RB1,RB2,RB3: PRadioButtons;
  4835. begin
  4836. R.Assign(0,0,56,15);
  4837. New(D, Init(R, 'Find'));
  4838. with D^ do
  4839. begin
  4840. Options:=Options or ofCentered;
  4841. GetExtent(R); R.Grow(-3,-2);
  4842. R1.Copy(R); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  4843. R2.Copy(R); R2.B.X:=R2.B.X-3;R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  4844. New(IL1, Init(R2, FindStrSize));
  4845. IL1^.Data^:=FindStr;
  4846. Insert(IL1);
  4847. Insert(New(PLabel, Init(R1, '~T~ext to find', IL1)));
  4848. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  4849. Control := New(PHistory, Init(R1, IL1, TextFindId));
  4850. Insert(Control);
  4851. 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;
  4852. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  4853. New(CB1, Init(R2,
  4854. NewSItem('~C~ase sensitive',
  4855. NewSItem('~W~hole words only',
  4856. nil))));
  4857. Insert(CB1);
  4858. Insert(New(PLabel, Init(R1, 'Options', CB1)));
  4859. 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;
  4860. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  4861. New(RB1, Init(R2,
  4862. NewSItem('Forwar~d~',
  4863. NewSItem('~B~ackward',
  4864. nil))));
  4865. Insert(RB1);
  4866. Insert(New(PLabel, Init(R1, 'Direction', RB1)));
  4867. 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;
  4868. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  4869. New(RB2, Init(R2,
  4870. NewSItem('~G~lobal',
  4871. NewSItem('~S~elected text',
  4872. nil))));
  4873. Insert(RB2);
  4874. Insert(New(PLabel, Init(R1, 'Scope', RB2)));
  4875. 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;
  4876. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  4877. New(RB3, Init(R2,
  4878. NewSItem('~F~rom cursor',
  4879. NewSItem('~E~ntire scope',
  4880. nil))));
  4881. Insert(RB3);
  4882. Insert(New(PLabel, Init(R1, 'Origin', RB3)));
  4883. GetExtent(R); R.Grow(-13,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10;
  4884. Insert(New(PButton, Init(R, 'O~K', cmOK, bfDefault)));
  4885. R.Move(19,0);
  4886. Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  4887. end;
  4888. IL1^.Select;
  4889. CreateFindDialog := D;
  4890. end;
  4891. function CreateReplaceDialog: PDialog;
  4892. var R,R1,R2: TRect;
  4893. D: PDialog;
  4894. Control : PView;
  4895. IL1,IL2: PInputLine;
  4896. CB1: PCheckBoxes;
  4897. RB1,RB2,RB3: PRadioButtons;
  4898. begin
  4899. R.Assign(0,0,56,18);
  4900. New(D, Init(R, 'Replace'));
  4901. with D^ do
  4902. begin
  4903. Options:=Options or ofCentered;
  4904. GetExtent(R); R.Grow(-3,-2);
  4905. R1.Copy(R); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  4906. R2.Copy(R); R2.B.X:=R2.B.X-3;R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  4907. New(IL1, Init(R2, FindStrSize));
  4908. IL1^.Data^:=FindStr;
  4909. Insert(IL1);
  4910. Insert(New(PLabel, Init(R1, '~T~ext to find', IL1)));
  4911. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  4912. Control := New(PHistory, Init(R1, IL1, TextFindId));
  4913. Insert(Control);
  4914. R1.Copy(R); R1.Move(0,2); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
  4915. R2.Copy(R); R2.Move(0,2);R2.B.X:=R2.B.X-3;
  4916. R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
  4917. New(IL2, Init(R2, FindStrSize));
  4918. IL2^.Data^:=ReplaceStr;
  4919. Insert(IL2);
  4920. Insert(New(PLabel, Init(R1, ' ~N~ew text', IL2)));
  4921. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  4922. Control := New(PHistory, Init(R1, IL2, TextReplaceId));
  4923. Insert(Control);
  4924. 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;
  4925. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+3;
  4926. New(CB1, Init(R2,
  4927. NewSItem('~C~ase sensitive',
  4928. NewSItem('~W~hole words only',
  4929. NewSItem('~P~rompt on replace',
  4930. nil)))));
  4931. Insert(CB1);
  4932. Insert(New(PLabel, Init(R1, 'Options', CB1)));
  4933. 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;
  4934. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  4935. New(RB1, Init(R2,
  4936. NewSItem('Forwar~d~',
  4937. NewSItem('~B~ackward',
  4938. nil))));
  4939. Insert(RB1);
  4940. Insert(New(PLabel, Init(R1, 'Direction', RB1)));
  4941. 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;
  4942. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  4943. New(RB2, Init(R2,
  4944. NewSItem('~G~lobal',
  4945. NewSItem('~S~elected text',
  4946. nil))));
  4947. Insert(RB2);
  4948. Insert(New(PLabel, Init(R1, 'Scope', RB2)));
  4949. 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;
  4950. R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
  4951. New(RB3, Init(R2,
  4952. NewSItem('~F~rom cursor',
  4953. NewSItem('~E~ntire scope',
  4954. nil))));
  4955. Insert(RB3);
  4956. Insert(New(PLabel, Init(R1, 'Origin', RB3)));
  4957. GetExtent(R); R.Grow(-13,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10; R.Move(-10,0);
  4958. Insert(New(PButton, Init(R, 'O~K~', cmOK, bfDefault)));
  4959. R.Move(11,0); R.B.X:=R.A.X+14;
  4960. Insert(New(PButton, Init(R, 'Change ~a~ll', cmYes, bfNormal)));
  4961. R.Move(15,0); R.B.X:=R.A.X+10;
  4962. Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  4963. end;
  4964. IL1^.Select;
  4965. CreateReplaceDialog := D;
  4966. end;
  4967. function CreateGotoLineDialog(Info: pointer): PDialog;
  4968. var D: PDialog;
  4969. R,R1,R2: TRect;
  4970. Control : PView;
  4971. IL: PInputLine;
  4972. begin
  4973. R.Assign(0,0,40,7);
  4974. New(D, Init(R, 'Goto line'));
  4975. with D^ do
  4976. begin
  4977. Options:=Options or ofCentered;
  4978. GetExtent(R); R.Grow(-3,-2); R.B.Y:=R.A.Y+1;
  4979. R1.Copy(R); R1.B.X:=27; R2.Copy(R);
  4980. R2.B.X:=R2.B.X-3;R2.A.X:=27;
  4981. New(IL, Init(R2,5));
  4982. with TGotoLineDialogRec(Info^) do
  4983. IL^.SetValidator(New(PRangeValidator, Init(1, Lines)));
  4984. Insert(IL);
  4985. Insert(New(PLabel, Init(R1, 'Enter new line ~n~umber', IL)));
  4986. R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
  4987. Control := New(PHistory, Init(R1, IL, GotoId));
  4988. Insert(Control);
  4989. GetExtent(R); R.Grow(-8,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10;
  4990. Insert(New(PButton, Init(R, 'O~K', cmOK, bfDefault)));
  4991. R.Move(15,0);
  4992. Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  4993. end;
  4994. IL^.Select;
  4995. CreateGotoLineDialog:=D;
  4996. end;
  4997. function StdEditorDialog(Dialog: Integer; Info: Pointer): Word;
  4998. var
  4999. R: TRect;
  5000. T: TPoint;
  5001. Re: word;
  5002. Name: string;
  5003. DriveNumber : byte;
  5004. StoreDir,StoreDir2 : DirStr;
  5005. Title,DefExt: string;
  5006. AskOW: boolean;
  5007. begin
  5008. case Dialog of
  5009. edOutOfMemory:
  5010. StdEditorDialog := MessageBox('Not enough memory for this operation.',
  5011. nil, mfInsertInApp+ mfError + mfOkButton);
  5012. edReadError:
  5013. StdEditorDialog := MessageBox('Error reading file %s.',
  5014. @Info, mfInsertInApp+ mfError + mfOkButton);
  5015. edWriteError:
  5016. StdEditorDialog := MessageBox('Error writing file %s.',
  5017. @Info, mfInsertInApp+ mfError + mfOkButton);
  5018. edCreateError:
  5019. StdEditorDialog := MessageBox('Error creating file %s.',
  5020. @Info, mfInsertInApp+ mfError + mfOkButton);
  5021. edSaveModify:
  5022. StdEditorDialog := MessageBox('%s has been modified. Save?',
  5023. @Info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  5024. edSaveUntitled:
  5025. StdEditorDialog := MessageBox('Save untitled file?',
  5026. nil, mfInsertInApp+ mfInformation + mfYesNoCancel);
  5027. edChangedOnloading:
  5028. StdEditorDialog := MessageBox(#3'File %s had too long lines'#13#3+
  5029. 'first such line is %d',
  5030. Info, mfInsertInApp+ mfOKButton + mfInformation);
  5031. edFileOnDiskChanged:
  5032. StdEditorDialog := MessageBox(#3'File %s '#13#3+
  5033. 'was modified by another program.'#13#3'Overwrite new version?',
  5034. @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
  5035. edSaveAs,edWriteBlock,edReadBlock:
  5036. begin
  5037. Name:=PString(Info)^;
  5038. GetDir(0,StoreDir);
  5039. DriveNumber:=0;
  5040. if (Length(FileDir)>1) and (FileDir[2]=':') then
  5041. begin
  5042. { does not assume that lowercase are greater then uppercase ! }
  5043. if (FileDir[1]>='a') and (FileDir[1]>='z') then
  5044. DriveNumber:=Ord(FileDir[1])-ord('a')+1
  5045. else
  5046. DriveNumber:=Ord(FileDir[1])-ord('A')+1;
  5047. GetDir(DriveNumber,StoreDir2);
  5048. {$ifndef FPC}
  5049. ChDir(Copy(FileDir,1,2));
  5050. { this sets InOutRes in win32 PM }
  5051. { is this bad? What about an EatIO? Gabor }
  5052. {$endif not FPC}
  5053. end;
  5054. if FileDir<>'' then
  5055. ChDir(FileDir);
  5056. case Dialog of
  5057. edSaveAs :
  5058. begin
  5059. Title:='Save File As';
  5060. DefExt:='*'+DefaultSaveExt;
  5061. end;
  5062. edWriteBlock :
  5063. begin
  5064. Title:='Write Block to File';
  5065. DefExt:='';
  5066. end;
  5067. edReadBlock :
  5068. begin
  5069. Title:='Read Block from File';
  5070. DefExt:='';
  5071. end;
  5072. else begin Title:='???'; DefExt:=''; end;
  5073. end;
  5074. Re:=Application^.ExecuteDialog(New(PFileDialog, Init(DefExt,
  5075. Title, '~N~ame', fdOkButton, FileId)), @Name);
  5076. case Dialog of
  5077. edSaveAs : AskOW:=(Name<>PString(Info)^);
  5078. edWriteBlock : AskOW:=true;
  5079. edReadBlock : AskOW:=false;
  5080. else AskOW:=true;
  5081. end;
  5082. if (Re<>cmCancel) and AskOW then
  5083. begin
  5084. FileDir:=DirOf(FExpand(Name));
  5085. if ExistsFile(Name) then
  5086. if EditorDialog(edReplaceFile,@Name)<>cmYes then
  5087. Re:=cmCancel;
  5088. end;
  5089. if DriveNumber<>0 then
  5090. ChDir(StoreDir2);
  5091. {$ifndef FPC}
  5092. if (Length(StoreDir)>1) and (StoreDir[2]=':') then
  5093. ChDir(Copy(StoreDir,1,2));
  5094. {$endif not FPC}
  5095. if StoreDir<>'' then
  5096. ChDir(StoreDir);
  5097. if Re<>cmCancel then
  5098. PString(Info)^:=Name;
  5099. StdEditorDialog := Re;
  5100. end;
  5101. edGotoLine:
  5102. StdEditorDialog :=
  5103. Application^.ExecuteDialog(CreateGotoLineDialog(Info), Info);
  5104. edFind:
  5105. StdEditorDialog :=
  5106. Application^.ExecuteDialog(CreateFindDialog, Info);
  5107. edSearchFailed:
  5108. StdEditorDialog := MessageBox('Search string not found.',
  5109. nil, mfInsertInApp+ mfError + mfOkButton);
  5110. edReplace:
  5111. StdEditorDialog :=
  5112. Application^.ExecuteDialog(CreateReplaceDialog, Info);
  5113. edReplacePrompt:
  5114. begin
  5115. { Avoid placing the dialog on the same line as the cursor }
  5116. R.Assign(0, 1, 40, 8);
  5117. R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  5118. Desktop^.MakeGlobal(R.B, T);
  5119. Inc(T.Y);
  5120. if PPoint(Info)^.Y <= T.Y then
  5121. R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  5122. StdEditorDialog := MessageBoxRect(R, 'Replace this occurence?',
  5123. nil, mfInsertInApp+ mfYesNoCancel + mfInformation);
  5124. end;
  5125. edReplaceFile :
  5126. StdEditorDialog :=
  5127. MessageBox('File %s already exists. Overwrite?',@Info,mfInsertInApp+mfConfirmation+
  5128. mfYesButton+mfNoButton);
  5129. end;
  5130. end;
  5131. function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
  5132. begin
  5133. DefUseSyntaxHighlight:=(Editor^.Flags and efSyntaxHighlight)<>0;
  5134. end;
  5135. function DefUseTabsPattern(Editor: PFileEditor): boolean;
  5136. begin
  5137. DefUseTabsPattern:=(Editor^.Flags and efUseTabCharacters)<>0;
  5138. end;
  5139. procedure RegisterCodeEditors;
  5140. begin
  5141. {$ifndef NOOBJREG}
  5142. RegisterType(RIndicator);
  5143. RegisterType(RCodeEditor);
  5144. RegisterType(RFileEditor);
  5145. {$endif}
  5146. end;
  5147. END.
  5148. {
  5149. $Log$
  5150. Revision 1.77 2000-01-27 22:30:38 florian
  5151. * start of FPU window
  5152. * current executed line color has a higher priority then a breakpoint now
  5153. Revision 1.76 2000/01/25 00:12:23 pierre
  5154. * fix for Backspace Undo
  5155. Revision 1.75 2000/01/14 15:36:42 pierre
  5156. + GetShortFileName used for tcodeeditor file opening
  5157. Revision 1.74 2000/01/10 23:20:04 pierre
  5158. * problem with Paste solved
  5159. Revision 1.73 2000/01/10 13:25:46 pierre
  5160. + first partial syntax test
  5161. Revision 1.72 2000/01/07 00:19:30 pierre
  5162. * forgot CommentLineType check to see if we need to update format
  5163. on next line
  5164. * some changes for TEST_PARTIAL_SYNTAX still does notwork :(
  5165. Revision 1.71 2000/01/06 17:47:26 pierre
  5166. * avoid to resyntax whole source in unnecessary cases
  5167. Revision 1.70 2000/01/05 17:35:50 pierre
  5168. + Warning box if a line is cut at reading of file
  5169. this is done to avoid loosing completely long lines
  5170. * several TAB related changes
  5171. in particular do not remove or recombine TABs in makefiles
  5172. * fixes for ^KR and ^KW (the was an extra LF at end of
  5173. written block of disk and an error for starting X position
  5174. in SaveAreaToStream)
  5175. Revision 1.69 2000/01/05 00:37:34 pierre
  5176. * ^KC fix
  5177. * better Tab handling
  5178. Revision 1.68 2000/01/04 12:33:08 pierre
  5179. * reinserted version 1.66 lost changes
  5180. + CtrlT Undo works now !
  5181. Revision 1.67 2000/01/03 11:38:35 michael
  5182. Changes from Gabor
  5183. Revision 1.65 1999/12/08 16:02:46 pierre
  5184. * fix for bugs 746,748 and 750
  5185. Revision 1.64 1999/12/01 17:25:00 pierre
  5186. + check if file on disk was changed since load before overwriting
  5187. Revision 1.63 1999/11/22 17:34:08 pierre
  5188. * fix for form bug 634
  5189. Revision 1.62 1999/11/18 13:42:06 pierre
  5190. * Some more Undo stuff
  5191. Revision 1.61 1999/11/10 00:45:30 pierre
  5192. + groupd action started, not yet working
  5193. Revision 1.60 1999/11/05 13:49:13 pierre
  5194. * WinPaste depends on avalaible Clipboard data
  5195. Revision 1.59 1999/11/03 09:39:23 peter
  5196. * fixed uppercase filenames
  5197. * savetostream did twice a -1 on the linecount, so the lastline of a
  5198. file wasn't saved correctly
  5199. Revision 1.58 1999/10/28 15:14:22 pierre
  5200. * get it to compile with debug conditional
  5201. Revision 1.56 1999/10/27 13:32:58 pierre
  5202. * some more Undo Fixes
  5203. Revision 1.55 1999/10/27 10:46:19 pierre
  5204. * More Undo/Redo stuff
  5205. Revision 1.54 1999/10/25 16:49:05 pierre
  5206. + Undo/Redo by Visa Harvey (great thanks) inserted
  5207. (with some modifications)
  5208. Moves work correctly
  5209. Text insertion/deletion are still buggy !
  5210. * LinePosToCharIndex and reverse function changed to get more
  5211. sensible results, dependant code adapted
  5212. * several bug fixes
  5213. Revision 1.53 1999/10/14 10:21:48 pierre
  5214. * more tabs related problems fiwes
  5215. Revision 1.52 1999/10/12 23:35:18 pierre
  5216. + DelStart and SelectWord implemented
  5217. * AddChar(tab) now reacts correctly if efAutoIndent is set
  5218. Revision 1.51 1999/10/08 15:24:50 pierre
  5219. * InsertFrom bug (end of line wasdiscarded)
  5220. Revision 1.50 1999/09/28 23:44:13 pierre
  5221. * text insertion in middle of line was buggy
  5222. Revision 1.49 1999/09/23 16:33:30 pierre
  5223. * ^B^A now prints out the ascii 1 char
  5224. * In SearchReplace Several occurence of a pattern in the same line
  5225. should now be found correctly
  5226. Revision 1.48 1999/09/22 16:16:26 pierre
  5227. + added HistLists for several dialogs
  5228. Revision 1.47 1999/09/21 17:08:59 pierre
  5229. + Windows clipboard for win32
  5230. Revision 1.46 1999/09/13 16:24:44 peter
  5231. + clock
  5232. * backspace unident like tp7
  5233. Revision 1.45 1999/09/09 12:05:33 pierre
  5234. + Copy/Paste to Windows Clipboard
  5235. + efLeaveTrailingSpaces added to editor flags
  5236. (if not set then spaces at the end of a line are
  5237. removed on writing the file)
  5238. Revision 1.44 1999/08/27 15:07:44 pierre
  5239. + cmResetDebuggerRow
  5240. Revision 1.43 1999/08/24 22:04:35 pierre
  5241. + TCodeEditor.SetDebuggerRow
  5242. works like SetHighlightRow but is only disposed by a SetDebuggerRow(-1)
  5243. so the current stop point in debugging is not lost if
  5244. we move the cursor
  5245. Revision 1.42 1999/08/22 22:20:30 pierre
  5246. * selection extension bug removed, via oldEvent pointer in TCodeEditor.HandleEvent
  5247. Revision 1.41 1999/08/16 18:25:28 peter
  5248. * Adjusting the selection when the editor didn't contain any line.
  5249. * Reserved word recognition redesigned, but this didn't affect the overall
  5250. syntax highlight speed remarkably (at least not on my Amd-K6/350).
  5251. The syntax scanner loop is a bit slow but the main problem is the
  5252. recognition of special symbols. Switching off symbol processing boosts
  5253. the performance up to ca. 200%...
  5254. * The editor didn't allow copying (for ex to clipboard) of a single character
  5255. * 'File|Save as' caused permanently run-time error 3. Not any more now...
  5256. * Compiler Messages window (actually the whole desktop) did not act on any
  5257. keypress when compilation failed and thus the window remained visible
  5258. + Message windows are now closed upon pressing Esc
  5259. + At 'Run' the IDE checks whether any sources are modified, and recompiles
  5260. only when neccessary
  5261. + BlockRead and BlockWrite (Ctrl+K+R/W) implemented in TCodeEditor
  5262. + LineSelect (Ctrl+K+L) implemented
  5263. * The IDE had problems closing help windows before saving the desktop
  5264. Revision 1.40 1999/08/03 20:22:42 peter
  5265. + TTab acts now on Ctrl+Tab and Ctrl+Shift+Tab...
  5266. + Desktop saving should work now
  5267. - History saved
  5268. - Clipboard content saved
  5269. - Desktop saved
  5270. - Symbol info saved
  5271. * syntax-highlight bug fixed, which compared special keywords case sensitive
  5272. (for ex. 'asm' caused asm-highlighting, while 'ASM' didn't)
  5273. * with 'whole words only' set, the editor didn't found occourences of the
  5274. searched text, if the text appeared previously in the same line, but didn't
  5275. satisfied the 'whole-word' condition
  5276. * ^QB jumped to (SelStart.X,SelEnd.X) instead of (SelStart.X,SelStart.Y)
  5277. (ie. the beginning of the selection)
  5278. * when started typing in a new line, but not at the start (X=0) of it,
  5279. the editor inserted the text one character more to left as it should...
  5280. * TCodeEditor.HideSelection (Ctrl-K+H) didn't update the screen
  5281. * Shift shouldn't cause so much trouble in TCodeEditor now...
  5282. * Syntax highlight had problems recognizing a special symbol if it was
  5283. prefixed by another symbol character in the source text
  5284. * Auto-save also occours at Dos shell, Tool execution, etc. now...
  5285. Revision 1.39 1999/07/28 23:11:26 peter
  5286. * fixes from gabor
  5287. Revision 1.38 1999/07/12 13:14:24 pierre
  5288. * LineEnd bug corrected, now goes end of text even if selected
  5289. + Until Return for debugger
  5290. + Code for Quit inside GDB Window
  5291. Revision 1.37 1999/06/29 22:50:16 peter
  5292. * more fixes from gabor
  5293. Revision 1.36 1999/06/29 08:51:34 pierre
  5294. * lockflag problems fixed
  5295. Revision 1.35 1999/06/28 19:32:32 peter
  5296. * fixes from gabor
  5297. Revision 1.34 1999/06/28 15:58:07 pierre
  5298. * ShiftDel problem solved
  5299. Revision 1.33 1999/06/25 00:31:51 pierre
  5300. + FileDir remembers the last directory for Open and Save
  5301. Revision 1.32 1999/06/21 23:36:12 pierre
  5302. * Size for Cluster is word (TP compatibility)
  5303. Revision 1.31 1999/05/22 13:44:35 peter
  5304. * fixed couple of bugs
  5305. Revision 1.30 1999/04/15 08:58:10 peter
  5306. * syntax highlight fixes
  5307. * browser updates
  5308. Revision 1.29 1999/04/07 21:55:59 peter
  5309. + object support for browser
  5310. * html help fixes
  5311. * more desktop saving things
  5312. * NODEBUG directive to exclude debugger
  5313. Revision 1.28 1999/03/23 15:11:39 peter
  5314. * desktop saving things
  5315. * vesa mode
  5316. * preferences dialog
  5317. Revision 1.27 1999/03/08 14:58:17 peter
  5318. + prompt with dialogs for tools
  5319. Revision 1.26 1999/03/07 22:58:57 pierre
  5320. * FindRec needs longint for CheckBoxes
  5321. Revision 1.25 1999/03/05 17:39:39 pierre
  5322. * Actions item freeing
  5323. Revision 1.24 1999/03/03 16:45:07 pierre
  5324. * Actions were not dispose in TCodeEditor.Done
  5325. Revision 1.23 1999/03/01 15:42:10 peter
  5326. + Added dummy entries for functions not yet implemented
  5327. * MenuBar didn't update itself automatically on command-set changes
  5328. * Fixed Debugging/Profiling options dialog
  5329. * TCodeEditor converts spaces to tabs at save only if efUseTabChars is set
  5330. * efBackSpaceUnindents works correctly
  5331. + 'Messages' window implemented
  5332. + Added '$CAP MSG()' and '$CAP EDIT' to available tool-macros
  5333. + Added TP message-filter support (for ex. you can call GREP thru
  5334. GREP2MSG and view the result in the messages window - just like in TP)
  5335. * A 'var' was missing from the param-list of THelpFacility.TopicSearch,
  5336. so topic search didn't work...
  5337. * In FPHELP.PAS there were still context-variables defined as word instead
  5338. of THelpCtx
  5339. * StdStatusKeys() was missing from the statusdef for help windows
  5340. + Topic-title for index-table can be specified when adding a HTML-files
  5341. Revision 1.22 1999/02/22 02:15:25 peter
  5342. + default extension for save in the editor
  5343. + Separate Text to Find for the grep dialog
  5344. * fixed redir crash with tp7
  5345. Revision 1.21 1999/02/20 15:18:33 peter
  5346. + ctrl-c capture with confirm dialog
  5347. + ascii table in the tools menu
  5348. + heapviewer
  5349. * empty file fixed
  5350. * fixed callback routines in fpdebug to have far for tp7
  5351. Revision 1.20 1999/02/18 17:27:57 pierre
  5352. * find/replace dialogs need packed records !!
  5353. Revision 1.19 1999/02/18 13:44:36 peter
  5354. * search fixed
  5355. + backward search
  5356. * help fixes
  5357. * browser updates
  5358. Revision 1.18 1999/02/15 15:12:25 pierre
  5359. + TLine remembers Comment type
  5360. Revision 1.17 1999/02/15 09:32:58 pierre
  5361. * single line comment // fix : comments intermix still wrong !!
  5362. Revision 1.16 1999/02/11 19:07:26 pierre
  5363. * GDBWindow redesigned :
  5364. normal editor apart from
  5365. that any kbEnter will send the line (for begin to cursor)
  5366. to GDB command !
  5367. GDBWindow opened in Debugger Menu
  5368. still buggy :
  5369. -echo should not be present if at end of text
  5370. -GDBWindow becomes First after each step (I don't know why !)
  5371. Revision 1.15 1999/02/09 09:29:59 pierre
  5372. * avoid invisible characters in CombineColors
  5373. Revision 1.14 1999/02/05 13:51:45 peter
  5374. * unit name of FPSwitches -> FPSwitch which is easier to use
  5375. * some fixes for tp7 compiling
  5376. Revision 1.13 1999/02/05 13:22:43 pierre
  5377. * bug that caused crash for empty files
  5378. Revision 1.12 1999/02/05 12:04:56 pierre
  5379. + 'loose' centering for debugger
  5380. Revision 1.11 1999/02/04 17:19:26 peter
  5381. * linux fixes
  5382. Revision 1.10 1999/02/04 10:13:00 pierre
  5383. + GetCurrentWord (used in Find/Replace)
  5384. + DefUseTabsPattern (pattern forcing tabs to be kept)
  5385. used for all makefiles !!
  5386. Revision 1.9 1999/01/29 10:34:33 peter
  5387. + needobjdir,needlibdir
  5388. Revision 1.8 1999/01/21 11:54:31 peter
  5389. + tools menu
  5390. + speedsearch in symbolbrowser
  5391. * working run command
  5392. Revision 1.7 1999/01/14 21:41:17 peter
  5393. * use * as modified indicator
  5394. * fixed syntax highlighting
  5395. Revision 1.6 1999/01/12 14:29:44 peter
  5396. + Implemented still missing 'switch' entries in Options menu
  5397. + Pressing Ctrl-B sets ASCII mode in editor, after which keypresses (even
  5398. ones with ASCII < 32 ; entered with Alt+<###>) are interpreted always as
  5399. ASCII chars and inserted directly in the text.
  5400. + Added symbol browser
  5401. * splitted fp.pas to fpide.pas
  5402. Revision 1.5 1999/01/07 15:02:40 peter
  5403. * better tab support
  5404. Revision 1.4 1999/01/04 11:49:55 peter
  5405. * 'Use tab characters' now works correctly
  5406. + Syntax highlight now acts on File|Save As...
  5407. + Added a new class to syntax highlight: 'hex numbers'.
  5408. * There was something very wrong with the palette managment. Now fixed.
  5409. + Added output directory (-FE<xxx>) support to 'Directories' dialog...
  5410. * Fixed some possible bugs in Running/Compiling, and the compilation/run
  5411. process revised
  5412. Revision 1.2 1998/12/28 15:47:55 peter
  5413. + Added user screen support, display & window
  5414. + Implemented Editor,Mouse Options dialog
  5415. + Added location of .INI and .CFG file
  5416. + Option (INI) file managment implemented (see bottom of Options Menu)
  5417. + Switches updated
  5418. + Run program
  5419. Revision 1.4 1998/12/27 12:01:23 gabor
  5420. * efXXXX constants revised for BP compatibility
  5421. * fixed column and row highlighting (needs to rewrite default palette in the INI)
  5422. Revision 1.3 1998/12/22 10:39:54 peter
  5423. + options are now written/read
  5424. + find and replace routines
  5425. }