weditor.pas 224 KB

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