weditor.pas 231 KB

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