GLS.Memo.pas 139 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit GLS.Memo;
  5. (* Memo for GLScene *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. WinApi.Windows,
  10. WinApi.Messages,
  11. System.SysUtils,
  12. System.Classes,
  13. System.UITypes,
  14. VCL.Graphics,
  15. VCL.Controls,
  16. VCL.Forms,
  17. VCL.Dialogs,
  18. VCL.ClipBrd,
  19. VCL.StdCtrls,
  20. VCL.ExtCtrls;
  21. type
  22. TBorderType = (btRaised, btLowered, btFlatRaised, btFlatLowered);
  23. TCommand = Integer;
  24. TCellSize = record
  25. W, H: integer;
  26. end;
  27. TCellPos = record
  28. X, Y: integer;
  29. end;
  30. TFullPos = record
  31. LineNo, Pos: integer;
  32. end;
  33. TLineProp = class
  34. FObject: TObject;
  35. FStyleNo: integer;
  36. FInComment: Boolean;
  37. FInBrackets: integer;
  38. FValidAttrs: Boolean;
  39. FCharAttrs: string;
  40. end;
  41. TCharStyle = class(TPersistent)
  42. private
  43. FTextColor, FBkColor: TColor;
  44. FStyle: TFontStyles;
  45. published
  46. property TextColor: TColor read FTextColor write FTextColor;
  47. property BkColor: TColor read FBkColor write FBkColor;
  48. property Style: TFontStyles read FStyle write FStyle;
  49. end;
  50. TStyleList = class(TList)
  51. private
  52. procedure CheckRange(Index: integer);
  53. function GetTextColor(Index: Integer): TColor;
  54. procedure SetTextColor(Index: Integer; Value: TColor);
  55. function GetBkColor(Index: Integer): TColor;
  56. procedure SetBkColor(Index: Integer; Value: TColor);
  57. function GetStyle(Index: Integer): TFontStyles;
  58. procedure SetStyle(Index: Integer; Value: TFontStyles);
  59. protected
  60. property TextColor[Index: Integer]: TColor read GetTextColor write
  61. SetTextColor;
  62. property BkColor[Index: Integer]: TColor read GetBkColor write SetBkColor;
  63. property Style[Index: Integer]: TFontStyles read GetStyle write SetStyle;
  64. public
  65. destructor Destroy; override;
  66. procedure Clear; override;
  67. procedure Delete(Index: Integer);
  68. function Add(ATextColor, ABkCOlor: TColor; AStyle: TFontStyles): Integer;
  69. procedure Change(Index: integer; ATextColor, ABkColor: TColor; AStyle:
  70. TFontStyles);
  71. end;
  72. TGLAbstractMemoObject = class(TObject)
  73. public
  74. function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
  75. Boolean; virtual; abstract;
  76. function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
  77. Boolean; virtual; abstract;
  78. function MouseMove(Shift: TShiftState; X, Y: Integer):
  79. Boolean; virtual; abstract;
  80. end;
  81. TGLSMemoScrollBar = class;
  82. TGLSMemoAbstractScrollableObject = class(TCustomControl)
  83. protected
  84. procedure DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
  85. virtual; abstract;
  86. procedure DoScrollPage(Sender: TGLSMemoScrollBar; ByValue: integer);
  87. virtual; abstract;
  88. end;
  89. TGLSCustomMemo = class;
  90. TsbState =
  91. (
  92. sbsWait,
  93. sbsBack,
  94. sbsForward,
  95. sbsPageBack,
  96. sbsPageForward,
  97. sbsDragging
  98. );
  99. TGLSMemoScrollBar = class(TGLAbstractMemoObject)
  100. private
  101. FKind: TScrollBarKind;
  102. FParent: TGLSMemoAbstractScrollableObject;
  103. FLeft, FTop, FWidth, FHeight: integer;
  104. FTotal, FMaxPosition, FPosition: integer;
  105. FButtonLength: integer;
  106. FState: TsbState;
  107. FXOffset, FYOffset: integer;
  108. procedure SetParams(Index: integer; Value: integer);
  109. procedure SetState(Value: TsbState);
  110. function GetRect: TRect;
  111. function GetThumbRect: TRect;
  112. function GetBackRect: TRect;
  113. function GetMiddleRect: TRect;
  114. function GetForwardRect: TRect;
  115. function GetPgBackRect: TRect;
  116. function GetPgForwardRect: TRect;
  117. public
  118. constructor Create(AParent: TGLSMemoAbstractScrollableObject;
  119. AKind: TScrollBarKind);
  120. procedure PaintTo(ACanvas: TCanvas);
  121. function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
  122. Boolean; override;
  123. function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
  124. Boolean; override;
  125. function MouseMove(Shift: TShiftState; X, Y: Integer):
  126. Boolean; override;
  127. function MoveThumbTo(X, Y: Integer): integer;
  128. property Parent: TGLSMemoAbstractScrollableObject read FParent;
  129. property Kind: TScrollBarKind read FKind write FKind;
  130. property State: TsbState read FState write SetState;
  131. property Left: integer index 0 read FLeft write SetParams;
  132. property Top: integer index 1 read FTop write SetParams;
  133. property Width: integer index 2 read FWidth write SetParams;
  134. property Height: integer index 3 read FHeight write SetParams;
  135. property Total: integer index 4 read FTotal write SetParams;
  136. property MaxPosition: integer index 5 read FMaxPosition write SetParams;
  137. property Position: integer index 6 read FPosition write SetParams;
  138. property FullRect: TRect read GetRect;
  139. property ThumbRect: TRect read GetThumbRect;
  140. property BackRect: TRect read GetBackRect;
  141. property MiddleRect: TRect read GetMiddleRect;
  142. property ForwardRect: TRect read GetForwardRect;
  143. property PageForwardRect: TRect read GetPgForwardRect;
  144. property PageBackRect: TRect read GetPgBackRect;
  145. end;
  146. TGLSMemoStrings = class(TStringList)
  147. private
  148. FMemo: TGLSCustomMemo;
  149. FLockCount: integer;
  150. FDeleting: Boolean;
  151. procedure CheckRange(Index: integer);
  152. function GetLineProp(Index: integer): TLineProp;
  153. procedure SetLineStyle(Index: integer; Value: integer);
  154. function GetLineStyle(Index: integer): integer;
  155. function GetInComment(Index: Integer): Boolean;
  156. procedure SetInComment(Index: Integer; Value: Boolean);
  157. function GetInBrackets(Index: Integer): integer;
  158. procedure SetInBrackets(Index: Integer; Value: integer);
  159. function GetValidAttrs(Index: Integer): Boolean;
  160. procedure SetValidAttrs(Index: Integer; Value: Boolean);
  161. function GetCharAttrs(Index: Integer): string;
  162. procedure SetCharAttrs(Index: Integer; const Value: string);
  163. protected
  164. function GetObject(Index: Integer): TObject; override;
  165. procedure PutObject(Index: Integer; AObject: TObject); override;
  166. procedure SetUpdateState(Updating: Boolean); override;
  167. function CreateProp(Index: integer): TLineProp;
  168. property LineProp[Index: integer]: TLineProp read GetLineProp; //PALOFF
  169. property Style[Index: integer]: integer read GetLineStyle write
  170. SetLineStyle;
  171. property InComment[Index: integer]: Boolean read GetInComment write
  172. SetInComment;
  173. property InBrackets[Index: integer]: integer read GetInBrackets write
  174. SetInBrackets;
  175. property ValidAttrs[Index: integer]: Boolean read GetValidAttrs write
  176. SetValidAttrs;
  177. property CharAttrs[Index: integer]: string read GetCharAttrs write
  178. SetCharAttrs;
  179. public
  180. destructor Destroy; override;
  181. procedure Clear; override;
  182. function DoAdd(const S: string): Integer;
  183. function Add(const S: string): Integer; override;
  184. function AddObject(const S: string; AObject: TObject): Integer; override;
  185. procedure Assign(Source: TPersistent); override;
  186. procedure Insert(Index: Integer; const S: string); override;
  187. procedure DoInsert(Index: Integer; const S: string);
  188. procedure InsertObject(Index: Integer; const S: string; AObject: TObject);
  189. override;
  190. procedure Delete(Index: Integer); override;
  191. procedure LoadFromFile(const FileName: string); override;
  192. end;
  193. TGLSMemoGutter = class(TObject)
  194. private
  195. FMemo: TGLSCustomMemo;
  196. FLeft, FTop, FWidth, FHeight: integer;
  197. FColor: TColor;
  198. procedure SetParams(Index: integer; Value: integer);
  199. function GetRect: TRect;
  200. protected
  201. procedure PaintTo(ACanvas: TCanvas);
  202. procedure Invalidate;
  203. public
  204. property Left: integer index 0 read FLeft write SetParams;
  205. property Top: integer index 1 read FTop write SetParams;
  206. property Width: integer index 2 read FWidth write SetParams;
  207. property Height: integer index 3 read FHeight write SetParams;
  208. property FullRect: TRect read GetRect;
  209. end;
  210. TGLSMemoUndo = class
  211. private
  212. FMemo: TGLSCustomMemo;
  213. FUndoCurX0, FUndoCurY0: integer;
  214. FUndoCurX, FUndoCurY: integer;
  215. FUndoText: string;
  216. public
  217. constructor Create(ACurX0, ACurY0, ACurX, ACurY: integer; const AText: string);
  218. function Append(NewUndo: TGLSMemoUndo): Boolean; virtual;
  219. procedure Undo;
  220. procedure Redo;
  221. procedure PerformUndo; virtual; abstract;
  222. procedure PerformRedo; virtual; abstract;
  223. property UndoCurX0: integer read FUndoCurX0 write FUndoCurX0;
  224. property UndoCurY0: integer read FUndoCurY0 write FUndoCurY0;
  225. property UndoCurX: integer read FUndoCurX write FUndoCurX;
  226. property UndoCurY: integer read FUndoCurY write FUndoCurY;
  227. end;
  228. TGLSMemoInsCharUndo = class(TGLSMemoUndo)
  229. public
  230. function Append(NewUndo: TGLSMemoUndo): Boolean; override;
  231. procedure PerformUndo; override;
  232. procedure PerformRedo; override;
  233. end;
  234. TGLSMemoDelCharUndo = class(TGLSMemoUndo)
  235. private
  236. FIsBackspace: Boolean;
  237. public
  238. function Append(NewUndo: TGLSMemoUndo): Boolean; override;
  239. procedure PerformUndo; override;
  240. procedure PerformRedo; override;
  241. property IsBackspace: Boolean read FIsBackspace write FIsBackspace;
  242. end;
  243. TGLSMEmoDelLineUndo = class(TGLSMemoUndo)
  244. private
  245. FIndex: integer;
  246. public
  247. constructor Create(AIndex, ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
  248. string);
  249. procedure PerformUndo; override;
  250. procedure PerformRedo; override;
  251. end;
  252. TGLSMemoSelUndo = class(TGLSMemoUndo)
  253. private
  254. FUndoSelStartX, FUndoSelStartY,
  255. FUndoSelEndX, FUndoSelEndY: integer;
  256. public
  257. property UndoSelStartX: integer read FUndoSelStartX write FUndoSelStartX;
  258. property UndoSelStartY: integer read FUndoSelStartY write FUndoSelStartY;
  259. property UndoSelEndX: integer read FUndoSelEndX write FUndoSelEndX;
  260. property UndoSelEndY: integer read FUndoSelEndY write FUndoSelEndY;
  261. end;
  262. TGLSMemoDeleteBufUndo = class(TGLSMemoSelUndo)
  263. public
  264. procedure PerformUndo; override;
  265. procedure PerformRedo; override;
  266. end;
  267. TGLSMemoPasteUndo = class(TGLSMemoUndo)
  268. public
  269. procedure PerformUndo; override;
  270. procedure PerformRedo; override;
  271. end;
  272. TGLSMemoUndoList = class(TList)
  273. private
  274. FPos: integer;
  275. FMemo: TGLSCustomMemo;
  276. FIsPerforming: Boolean;
  277. FLimit: integer;
  278. protected
  279. function Get(Index: Integer): TGLSMemoUndo;
  280. procedure SetLimit(Value: integer);
  281. public
  282. constructor Create;
  283. destructor Destroy; override;
  284. function Add(Item: Pointer): Integer;
  285. procedure Clear; override;
  286. procedure Delete(Index: Integer);
  287. procedure Undo;
  288. procedure Redo;
  289. property Items[Index: Integer]: TGLSMemoUndo read Get; default;
  290. property IsPerforming: Boolean read FIsPerforming write FIsPerforming;
  291. property Memo: TGLSCustomMemo read FMemo write FMemo;
  292. property Pos: integer read FPos write FPos;
  293. property Limit: integer read FLimit write SetLimit;
  294. end;
  295. //--------------------------------------------------------------
  296. TGutterClickEvent = procedure(Sender: TObject; LineNo: integer) of object;
  297. TGutterDrawEvent = procedure(Sender: TObject; ACanvas: TCanvas;
  298. LineNo: integer; rct: TRect) of object;
  299. TGetLineAttrsEvent = procedure(Sender: TObject; LineNo: integer;
  300. var Attrs: string) of object;
  301. TUndoChangeEvent = procedure(Sender: TObject;
  302. CanUndo, CanRedo: Boolean) of object;
  303. TScrollMode = (smAuto, smStrict);
  304. TGLSCustomMemo = class(TGLSMemoAbstractScrollableObject)
  305. private
  306. FAutoIndent: Boolean;
  307. FMargin: integer;
  308. FHiddenCaret, FCaretVisible: Boolean;
  309. FCellSize: TCellSize;
  310. FCurX, FCurY: integer;
  311. FLeftCol, FTopLine: integer;
  312. FTabSize: integer;
  313. FFont: TFont;
  314. FBkColor: TColor;
  315. FSelColor: TColor;
  316. FSelBkColor: TColor;
  317. FReadOnly: Boolean;
  318. FDelErase: Boolean;
  319. FLines: TStrings;
  320. FSelStartX, FSelStartY,
  321. FSelEndX, FSelEndY,
  322. FPrevSelX, FPrevSelY: integer;
  323. FScrollBars: System.UITypes.TScrollStyle;
  324. FScrollBarWidth: integer;
  325. FGutter: TGLSMemoGutter;
  326. FGutterWidth: integer;
  327. sbVert, sbHorz: TGLSMemoScrollBar;
  328. FStyles: TStyleList;
  329. FLineBitmap: TBitmap;
  330. FSelCharPos: TFullPos;
  331. FSelCharStyle: integer;
  332. FLeftButtonDown: Boolean;
  333. FScrollMode: TScrollMode;
  334. FUndoList: TGLSMemoUndoList;
  335. FFirstUndoList: TGLSMemoUndoList;
  336. FUndoLimit: integer;
  337. FLastMouseUpX,
  338. FLastMouseUpY: integer;
  339. FAfterDoubleClick: Boolean;
  340. // events
  341. FOnMoveCursor: TNotifyEvent;
  342. FOnChange: TNotifyEvent;
  343. FOnAttrChange: TNotifyEvent;
  344. FOnStatusChange: TNotifyEvent;
  345. FOnSelectionChange: TNotifyEvent;
  346. FOnGutterDraw: TGutterDrawEvent;
  347. FOnGutterClick: TGutterClickEvent;
  348. FOnGetLineAttrs: TGetLineAttrsEvent;
  349. FOnUndoChange: TUndoChangeEvent;
  350. FHideCursor: Boolean;
  351. procedure SetHiddenCaret(Value: Boolean);
  352. procedure SetScrollBars(Value: System.UITypes.TScrollStyle);
  353. procedure SetGutterWidth(Value: integer);
  354. procedure SetGutterColor(Value: TColor);
  355. function GetGutterColor: TColor;
  356. procedure SetCurX(Value: integer);
  357. procedure SetCurY(Value: integer);
  358. procedure SetFont(Value: TFont);
  359. procedure SetColor(Index: integer; Value: TColor);
  360. function GetSelStart: TPoint;
  361. function GetSelEnd: TPoint;
  362. procedure SetLines(ALines: TStrings);
  363. procedure SetLineStyle(Index: integer; Value: integer);
  364. function GetLineStyle(Index: integer): integer;
  365. function GetInComment(Index: integer): Boolean;
  366. procedure SetInComment(Index: integer; Value: Boolean);
  367. function GetInBrackets(Index: Integer): integer;
  368. procedure SetInBrackets(Index: Integer; Value: integer);
  369. function GetValidAttrs(Index: integer): Boolean;
  370. procedure SetValidAttrs(Index: integer; Value: Boolean);
  371. function GetCharAttrs(Index: integer): string;
  372. procedure SetCharAttrs(Index: integer; const Value: string);
  373. procedure ExpandSelection;
  374. function GetSelText: string;
  375. procedure SetSelText(const AValue: string);
  376. function GetSelLength: integer;
  377. procedure MovePage(dP: integer; Shift: TShiftState);
  378. procedure ShowCaret(State: Boolean);
  379. procedure MakeVisible;
  380. function GetVisible(Index: integer): integer;
  381. function MaxLength: integer;
  382. procedure WMSize(var Msg: TWMSize); message WM_SIZE;
  383. procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
  384. procedure WMEraseBkgnd(var Msg: TWmEraseBkgnd); message WM_ERASEBKGND;
  385. procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
  386. procedure WMSetFocus(var Msg: TWMSetFocus); message WM_SETFOCUS;
  387. procedure WMKillFocus(var Msg: TWMSetFocus); message WM_KILLFOCUS;
  388. procedure WMMouseWheel(var Message: TMessage); message WM_MOUSEWHEEL;
  389. procedure MoveCursor(dX, dY: integer; Shift: TShiftState);
  390. procedure ResizeEditor;
  391. procedure ResizeScrollBars;
  392. procedure ResizeGutter;
  393. procedure DoCommand(cmd: TCommand; const AShift: TShiftState);
  394. procedure DrawLine(LineNo: integer);
  395. function IsLineVisible(LineNo: integer): Boolean;
  396. procedure FreshLineBitmap;
  397. procedure SetUndoLimit(Value: integer);
  398. protected
  399. procedure WndProc(var Message: TMessage); override;
  400. function EditorRect: TRect;
  401. function LineRangeRect(FromLine, ToLine: integer): TRect;
  402. function ColRangeRect(FromCol, ToCol: integer): TRect;
  403. procedure InvalidateLineRange(FromLine, ToLine: integer);
  404. function AddString(const S: string): integer;
  405. procedure InsertString(Index: integer; S: string);
  406. procedure GoHome(Shift: TShiftState);
  407. procedure GoEnd(Shift: TShiftState);
  408. procedure InsertChar(C: Char);
  409. procedure DeleteChar(OldX, OldY: integer);
  410. procedure DeleteLine(Index, OldX, OldY, NewX, NewY: integer; FixUndo: Boolean);
  411. procedure BackSpace;
  412. procedure BackSpaceWord;
  413. function IndentCurrLine: string;
  414. procedure NewLine;
  415. procedure CreateParams(var Params: TCreateParams); override;
  416. procedure Paint; override;
  417. procedure DrawMargin;
  418. procedure DrawGutter;
  419. procedure DrawScrollBars;
  420. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  421. procedure KeyPress(var Key: Char); override;
  422. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  423. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  424. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  425. procedure DblClick; override;
  426. procedure DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer); override;
  427. procedure DoScrollPage(Sender: TGLSMemoScrollBar; ByValue: integer); override;
  428. property VisiblePosCount: integer index 0 read GetVisible;
  429. property VisibleLineCount: integer index 1 read GetVisible;
  430. property LastVisiblePos: integer index 2 read GetVisible;
  431. property LastVisibleLine: integer index 3 read GetVisible;
  432. procedure DeleteSelection(bRepaint: Boolean);
  433. procedure Changed(FromLine, ToLine: integer); virtual;
  434. procedure AttrChanged(LineNo: integer); virtual;
  435. procedure SelectionChanged; virtual;
  436. procedure StatusChanged; virtual;
  437. procedure ClearUndoList;
  438. procedure UndoChange;
  439. property AutoIndent: Boolean read FAutoIndent write FAutoIndent;
  440. property GutterWidth: integer read FGutterWidth write SetGutterWidth;
  441. property GutterColor: TColor read GetGutterColor write SetGutterColor;
  442. property ScrollBars: System.UITypes.TScrollStyle read FScrollBars write SetScrollBars default ssBoth;
  443. property Font: TFont read FFont write SetFont;
  444. property ReadOnly: Boolean read FReadOnly write FReadOnly;
  445. property Lines: TStrings read FLines write SetLines;
  446. property BkColor: TColor index 0 read FBkColor write SetColor;
  447. property SelColor: TColor index 1 read FSelColor write SetColor;
  448. property SelBkColor: TColor index 2 read FSelBkColor write SetColor;
  449. property HiddenCaret: Boolean read FHiddenCaret write SetHiddenCaret;
  450. property TabSize: integer read FTabSize write FTabSize;
  451. property ScrollMode: TScrollMode read FScrollMode write FScrollMode default smAuto;
  452. property UndoLimit: integer read FUndoLimit write SetUndoLimit;
  453. property HideCursor: Boolean read FHideCursor write FHideCursor;
  454. property InComment[Index: integer]: Boolean read GetInComment write SetInComment;
  455. property InBrackets[Index: integer]: integer read GetInBrackets write SetInBrackets;
  456. property ValidAttrs[Index: integer]: Boolean read GetValidAttrs write SetValidAttrs;
  457. property CharAttrs[Index: integer]: string read GetCharAttrs write SetCharAttrs;
  458. {events}
  459. property OnGutterClick: TGutterClickEvent read FOnGutterClick write FOnGutterClick;
  460. property OnGutterDraw: TGutterDrawEvent read FOnGutterDraw write FOnGutterDraw;
  461. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  462. property OnMoveCursor: TNotifyEvent read FOnMoveCursor write FOnMoveCursor;
  463. property OnAttrChange: TNotifyEvent read FOnAttrChange write FOnAttrChange;
  464. property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange;
  465. property OnStatusChange: TNotifyEvent read FOnStatusChange write FOnStatusChange;
  466. property OnGetLineAttrs: TGetLineAttrsEvent read FOnGetLineAttrs write FOnGetLineAttrs;
  467. property OnUndoChange: TUndoChangeEvent read FOnUndoChange write FOnUndoChange;
  468. public
  469. constructor Create(AOwner: TComponent); override;
  470. destructor Destroy; override;
  471. procedure CopyToClipBoard;
  472. procedure PasteFromClipBoard;
  473. procedure CutToClipBoard;
  474. procedure SelectLines(StartLine, EndLine: Integer);
  475. procedure SelectAll;
  476. property SelStart: TPoint read GetSelStart;
  477. property SelEnd: TPoint read GetSelEnd;
  478. property Selection: string read GetSelText write SetSelText;
  479. property SelLength: integer read GetSelLength;
  480. procedure ClearSelection;
  481. procedure Clear;
  482. procedure SetCursor(ACurX, ACurY: Integer);
  483. function SelectLine(LineNo, StyleNo: Integer): integer;
  484. procedure SelectChar(LineNo, Pos, StyleNo: Integer);
  485. function CellFromPos(X, Y: integer): TCellPos;
  486. function CharFromPos(X, Y: integer): TFullPos;
  487. function CellRect(ACol, ARow: integer): TRect;
  488. function LineRect(ARow: integer): TRect;
  489. function ColRect(ACol: integer): TRect;
  490. function CharStyleNo(LineNo, Pos: integer): integer;
  491. procedure InsertTemplate(AText: string);
  492. procedure UnSelectChar;
  493. procedure Undo;
  494. procedure Redo;
  495. function CanUndo: Boolean;
  496. function CanRedo: Boolean;
  497. function FindText(Text: string; Options: TFindOptions; Select: Boolean): Boolean;
  498. property CurX: integer read FCurX write SetCurX;
  499. property CurY: integer read FCurY write SetCurY;
  500. property DelErase: Boolean read FDelErase write FDelErase;
  501. property LineStyle[Index: integer]: integer read GetLineStyle write
  502. SetLineStyle;
  503. property Styles: TStyleList read FStyles;
  504. property UndoList: TGLSMemoUndoList read FUndoList write FUndoList;
  505. end;
  506. TGLSMemo = class(TGLSCustomMemo)
  507. published
  508. {TControl }
  509. property PopupMenu;
  510. {TCustomControl }
  511. property Align;
  512. property Enabled;
  513. property ShowHint;
  514. property TabOrder;
  515. property TabStop;
  516. property Visible;
  517. property ReadOnly;
  518. {TGLSCustomMemo }
  519. property AutoIndent;
  520. property GutterColor;
  521. property GutterWidth;
  522. property ScrollBars;
  523. property Font;
  524. property BkColor;
  525. property Selection;
  526. property SelColor;
  527. property SelBkColor;
  528. property Lines;
  529. property HiddenCaret;
  530. property TabSize;
  531. property ScrollMode;
  532. property UndoLimit;
  533. property DelErase;
  534. {Inherited events }
  535. property OnClick;
  536. property OnDblClick;
  537. property OnDragDrop;
  538. property OnDragOver;
  539. property OnEndDrag;
  540. property OnMouseDown;
  541. property OnMouseMove;
  542. property OnMouseUp;
  543. property OnStartDrag;
  544. property OnEnter;
  545. property OnExit;
  546. property OnKeyDown;
  547. property OnKeyPress;
  548. property OnKeyUp;
  549. {Events }
  550. property OnGutterDraw;
  551. property OnGutterClick;
  552. property OnChange;
  553. property OnMoveCursor;
  554. property OnAttrChange;
  555. property OnSelectionChange;
  556. property OnStatusChange;
  557. property OnGetLineAttrs;
  558. property OnUndoChange;
  559. end;
  560. TGLSMemoStringList = class(TStringList)
  561. private
  562. procedure ReadStrings(Reader: TReader);
  563. procedure WriteStrings(Writer: TWriter);
  564. protected
  565. procedure DefineProperties(Filer: TFiler); override;
  566. end;
  567. TDelimiters = TSysCharSet;
  568. TTokenType =
  569. (
  570. ttWord,
  571. ttBracket,
  572. ttSpecial,
  573. ttDelimiter,
  574. ttSpace,
  575. ttEOL,
  576. ttInteger,
  577. ttFloat,
  578. ttComment,
  579. ttOther,
  580. ttWrongNumber);
  581. //--------------------------------------------------------------
  582. // SYNTAX MEMO - declaration
  583. //--------------------------------------------------------------
  584. TGLSSynHiMemo = class(TGLSCustomMemo)
  585. private
  586. FIsPainting: Boolean;
  587. FInComment: Boolean;
  588. FWordList: TGLSMemoStringList;
  589. FSpecialList: TGLSMemoStringList;
  590. FBracketList: TGLSMemoStringList;
  591. FDelimiters: TDelimiters;
  592. FInBrackets: integer;
  593. FLineComment: string;
  594. FMultiCommentLeft: string;
  595. FMultiCommentRight: string;
  596. FDelimiterStyle: TCharStyle;
  597. FCommentStyle: TCharStyle;
  598. FNumberStyle: TCharStyle;
  599. FDelimiterStyleNo,
  600. FCommentStyleNo,
  601. FNumberStyleNo: integer;
  602. FCaseSensitive: Boolean;
  603. function GetToken(const S: string; var From: integer;
  604. out TokenType: TTokenType; out StyleNo: integer): string;
  605. procedure SetWordList(Value: TGLSMemoStringList);
  606. procedure SetSpecialList(Value: TGLSMemoStringList);
  607. procedure SetBracketList(Value: TGLSMemoStringList);
  608. procedure FindLineAttrs(Sender: TObject; LineNo: integer; var Attrs:
  609. string);
  610. procedure SetStyle(Index: integer; Value: TCharStyle);
  611. procedure SetCaseSensitive(Value: Boolean);
  612. protected
  613. procedure Paint; override;
  614. public
  615. constructor Create(AOwner: TComponent); override;
  616. destructor Destroy; override;
  617. procedure AddWord(StyleNo: integer; const ArrS: array of string);
  618. procedure AddSpecial(StyleNo: integer; const ArrS: array of string);
  619. procedure AddBrackets(StyleNo: integer; const ArrS: array of string);
  620. property Delimiters: TDelimiters read FDelimiters write FDelimiters;
  621. published
  622. {TControl}
  623. property PopupMenu;
  624. {TCustomControl}
  625. property Align;
  626. property Enabled;
  627. property ShowHint;
  628. property TabOrder;
  629. property TabStop;
  630. property Visible;
  631. property ReadOnly;
  632. {TGLSCustomMemo}
  633. property AutoIndent;
  634. property GutterColor;
  635. property GutterWidth;
  636. property ScrollBars;
  637. property Font;
  638. property BkColor;
  639. property SelColor;
  640. property SelBkColor;
  641. property Lines;
  642. property HiddenCaret;
  643. property TabSize;
  644. property ScrollMode;
  645. property UndoLimit;
  646. property DelErase;
  647. {Inherited events }
  648. property OnClick;
  649. property OnDblClick;
  650. property OnDragDrop;
  651. property OnDragOver;
  652. property OnEndDrag;
  653. property OnMouseDown;
  654. property OnMouseMove;
  655. property OnMouseUp;
  656. property OnStartDrag;
  657. property OnEnter;
  658. property OnExit;
  659. property OnKeyDown;
  660. property OnKeyPress;
  661. property OnKeyUp;
  662. {Events }
  663. property OnGutterClick;
  664. property OnGutterDraw;
  665. property OnChange;
  666. property OnMoveCursor;
  667. property OnSelectionChange;
  668. property OnStatusChange;
  669. property OnUndoChange;
  670. {TGLSSyntaxMemo }
  671. property LineComment: string read FLineComment write FLineComment;
  672. property MultiCommentLeft: string read FMultiCommentLeft write FMultiCommentLeft;
  673. property MultiCommentRight: string read FMultiCommentRight write FMultiCommentRight;
  674. property WordList: TGLSMemoStringList read FWordList write SetWordList;
  675. property SpecialList: TGLSMemoStringList read FSpecialList write SetSpecialList;
  676. property BracketList: TGLSMemoStringList read FBracketList write SetBracketList;
  677. property DelimiterStyle: TCharStyle index 0 read FDelimiterStyle write SetStyle;
  678. property CommentStyle: TCharStyle index 1 read FCommentStyle write SetStyle;
  679. property NumberStyle: TCharStyle index 2 read FNumberStyle write SetStyle;
  680. property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
  681. end;
  682. procedure Border(Canvas: TCanvas; const rct: TRect; BorderType: TBorderType);
  683. //==========================================================
  684. implementation
  685. //==========================================================
  686. const
  687. cmDelete = VK_DELETE;
  688. cmBackSpace = VK_BACK;
  689. cmWordBackSpace = 127; // Ctrl-BackSpace
  690. cmNewLine = VK_RETURN;
  691. cmHome = VK_HOME;
  692. cmEnd = VK_END;
  693. cmPageUp = VK_PRIOR;
  694. cmPageDown = VK_NEXT;
  695. cmInsert = VK_INSERT;
  696. cmDelLine = 25; // Ctrl-Y
  697. cmCopy = 3; // Ctrl-C
  698. cmCut = 24; // Ctrl-X
  699. cmPaste = 22; // Ctrl-V
  700. resourcestring
  701. SObjectsNotSupported = 'Linked object not supported';
  702. var
  703. bmScrollBarFill: TBitmap;
  704. bmScrollBarUp: TBitmap;
  705. bmScrollBarDown: TBitmap;
  706. bmScrollBarLeft: TBitmap;
  707. bmScrollBarRight: TBitmap;
  708. fIntelliWheelSupport: Boolean; // True if IntelliMouse + wheel enabled
  709. fIntelliMessage: UINT; // message sent from mouse on wheel roll
  710. fIntelliScrollLines: Integer; // number of lines to scroll per wheel roll
  711. // ---------------------Helper functions
  712. function PointInRect(const P: TPoint; const rct: TRect): Boolean; inline;
  713. begin
  714. with rct do
  715. Result := (Left <= P.X) and (Top <= P.Y) and
  716. (Right >= P.X) and (Bottom >= P.Y);
  717. end;
  718. procedure Swap(var I1, I2: integer); inline;
  719. var
  720. temp: integer;
  721. begin
  722. temp := I1;
  723. I1 := I2;
  724. I2 := temp;
  725. end;
  726. procedure OrderPos(var StartX, StartY, EndX, EndY: integer); inline;
  727. begin
  728. if (EndY < StartY) or
  729. ((EndY = StartY) and (EndX < StartX)) then
  730. begin
  731. Swap(StartX, EndX);
  732. Swap(StartY, EndY);
  733. end;
  734. end;
  735. function TotalRect(const rct1, rct2: TRect): TRect; inline;
  736. begin
  737. Result := rct1;
  738. with Result do
  739. begin
  740. if rct2.Left < Left then
  741. Left := rct2.Left;
  742. if rct2.Top < Top then
  743. Top := rct2.Top;
  744. if rct2.Right > Right then
  745. Right := rct2.Right;
  746. if rct2.Bottom > Bottom then
  747. Bottom := rct2.Bottom;
  748. end;
  749. end;
  750. // ---------------------TGLSCustomMemo functions
  751. procedure TGLSCustomMemo.WndProc(var Message: TMessage);
  752. function GetShiftState: Integer;
  753. begin
  754. Result := 0;
  755. if GetAsyncKeyState(vk_Shift) < 0 then
  756. Result := Result or mk_Shift;
  757. if GetAsyncKeyState(vk_Control) < 0 then
  758. Result := Result or mk_Control;
  759. if GetAsyncKeyState(vk_LButton) < 0 then
  760. Result := Result or mk_LButton;
  761. if GetAsyncKeyState(vk_RButton) < 0 then
  762. Result := Result or mk_RButton;
  763. if GetAsyncKeyState(vk_MButton) < 0 then
  764. Result := Result or mk_MButton;
  765. end;
  766. //---------------------------------------------------
  767. begin
  768. if (Message.Msg = fIntelliMessage) and (fIntelliMessage <> wm_MouseWheel) then
  769. begin
  770. PostMessage(Handle, wm_MouseWheel, MakeLong(GetShiftState, Message.wParam),
  771. Message.lParam);
  772. end
  773. else
  774. inherited;
  775. end;
  776. //------------------------------------------------
  777. // INTELLIMOUSE INIT
  778. //------------------------------------------------
  779. procedure IntelliMouseInit;
  780. var
  781. hWndMouse: hWnd;
  782. mQueryScrollLines: UINT;
  783. //--------------------------------------------
  784. function NativeMouseWheelSupport: Boolean;
  785. var
  786. ver: TOSVersionInfo;
  787. begin
  788. Result := False;
  789. ver.dwOSVersionInfoSize := sizeof(ver);
  790. // For Windows 98, assume dwMajorVersion = 5 (It's 4 for W95)
  791. // For NT, we need 4.0 or better.
  792. if GetVersionEx(ver) then
  793. case ver.dwPlatformID of
  794. ver_Platform_Win32_Windows: Result := ver.dwMajorVersion >= 5;
  795. ver_Platform_Win32_NT: Result := ver.dwMajorVersion >= 4;
  796. end;
  797. { Quick and dirty temporary hack for Windows 98 beta 3 }
  798. if (not Result) and (ver.szCSDVersion = ' Beta 3') then
  799. Result := True;
  800. end;
  801. //--------------------------------------------
  802. begin
  803. if NativeMouseWheelSupport then
  804. begin
  805. fIntelliWheelSupport := Boolean(GetSystemMetrics(sm_MouseWheelPresent));
  806. SystemParametersInfo(spi_GetWheelScrollLines, 0, @fIntelliScrollLines, 0);
  807. fIntelliMessage := wm_MouseWheel;
  808. end
  809. else
  810. begin
  811. { Look for hidden mouse window }
  812. hWndMouse := FindWindow('MouseZ', 'Magellan MSWHEEL');
  813. if hWndMouse <> 0 then
  814. begin
  815. { We're in business - get the scroll line info }
  816. fIntelliWheelSupport := True;
  817. mQueryScrollLines := RegisterWindowMessage('MSH_SCROLL_LINES_MSG');
  818. fIntelliScrollLines := SendMessage(hWndMouse, mQueryScrollLines, 0, 0);
  819. { Finally, get the custom mouse message as well }
  820. fIntelliMessage := RegisterWindowMessage('MSWHEEL_ROLLMSG');
  821. end;
  822. end;
  823. if (fIntelliScrollLines < 0) or (fIntelliScrollLines > 100) then
  824. fIntelliScrollLines := 3;
  825. end;
  826. //------------------------------------------------
  827. // WM MOUSE WHEEL
  828. //------------------------------------------------
  829. procedure TGLSCustomMemo.WMMouseWheel(var Message: TMessage);
  830. {$J+}
  831. {$IFOPT R+} {$DEFINE StoreRangeCheck} {$ENDIF} {$R-}
  832. const
  833. Delta: SmallInt = 0;
  834. begin
  835. Delta := Delta + SmallInt(HiWord(Message.wParam));
  836. while Abs(Delta) >= 120 do
  837. begin
  838. if Delta < 0 then
  839. begin
  840. DoScroll(sbVert, fIntelliScrollLines);
  841. Delta := Delta + 120;
  842. end
  843. else
  844. begin
  845. DoScroll(sbVert, -fIntelliScrollLines);
  846. Delta := Delta - 120;
  847. end;
  848. end;
  849. end;
  850. {$J-}
  851. {$IFDEF StoreRangeCheck} {$R+} {$UNDEF StoreRangeCheck} {$ENDIF}
  852. //--------------------------------------------------------------
  853. // SET CURSOR
  854. //--------------------------------------------------------------
  855. procedure TGLSCustomMemo.SetCursor(ACurX, ACurY: Integer);
  856. begin
  857. ClearSelection;
  858. CurX := 0;
  859. CurY := ACurY;
  860. CurX := ACurX;
  861. end;
  862. //--------------------------------------------------------------
  863. // SELECT LINE, CHAR
  864. //--------------------------------------------------------------
  865. function TGLSCustomMemo.SelectLine(LineNo, StyleNo: Integer): integer;
  866. var
  867. rct: TRect;
  868. begin
  869. Result := LineStyle[LineNo];
  870. LineStyle[LineNo] := StyleNo;
  871. rct := LineRect(LineNo);
  872. InvalidateRect(Handle, @rct, True);
  873. end;
  874. procedure TGLSCustomMemo.SelectLines(StartLine, EndLine: Integer);
  875. var
  876. rct: TRect;
  877. begin
  878. FSelStartX := 0;
  879. FSelStartY := StartLine;
  880. FSelEndX := Length(Lines[EndLine]);
  881. FSelEndY := EndLine;
  882. rct := LineRangeRect(FSelStartY, FSelEndY);
  883. SelectionChanged;
  884. InvalidateRect(Handle, @rct, true);
  885. end;
  886. procedure TGLSCustomMemo.SelectChar(LineNo, Pos, StyleNo: Integer);
  887. var
  888. rct: TRect;
  889. begin
  890. UnselectChar;
  891. FSelCharPos.LineNo := LineNo;
  892. FSelCharPos.Pos := Pos;
  893. FSelCharStyle := StyleNo;
  894. rct := LineRect(LineNo);
  895. InvalidateRect(Handle, @rct, True);
  896. end;
  897. procedure TGLSCustomMemo.UnSelectChar;
  898. var
  899. rct: TRect;
  900. begin
  901. with FSelCharPos do
  902. begin
  903. if LineNo < 0 then
  904. Exit;
  905. rct := LineRect(LineNo);
  906. LineNo := -1;
  907. Pos := -1;
  908. end;
  909. FSelCharStyle := -1;
  910. InvalidateRect(Handle, @rct, True);
  911. end;
  912. //--------------------------------------------------------------
  913. // CLEAR
  914. //--------------------------------------------------------------
  915. procedure TGLSCustomMemo.Clear;
  916. begin
  917. CurY := 0;
  918. CurX := 0;
  919. FLeftCol := 0;
  920. FTopLine := 0;
  921. Lines.Clear;
  922. TGLSMemoStrings(Lines).DoAdd('');
  923. ClearUndoList;
  924. Invalidate;
  925. end;
  926. //--------------------------------------------------------------
  927. // SELECT ALL
  928. //--------------------------------------------------------------
  929. procedure TGLSCustomMemo.SelectAll;
  930. begin
  931. FSelStartY := 0;
  932. FSelStartX := 0;
  933. FSelEndY := Lines.Count - 1;
  934. FSelEndX := Length(Lines[Lines.Count - 1]);
  935. Invalidate;
  936. end;
  937. //-----------------------------------------------------------
  938. // SET CLIPBOARD CODE PAGE
  939. //-----------------------------------------------------------
  940. procedure SetClipboardCodePage(const CodePage: longint);
  941. var
  942. Data: THandle;
  943. DataPtr: Pointer;
  944. begin
  945. // Define new code page for clipboard
  946. Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, 4);
  947. try
  948. DataPtr := GlobalLock(Data);
  949. try
  950. Move(CodePage, DataPtr^, 4);
  951. SetClipboardData(CF_LOCALE, Data);
  952. finally
  953. GlobalUnlock(Data);
  954. end;
  955. except
  956. GlobalFree(Data);
  957. end;
  958. end;
  959. //--------------------------------------------------------------
  960. // COPY TO CLIPBOARD
  961. //--------------------------------------------------------------
  962. procedure CopyStringToClipboard(const Value: string);
  963. const
  964. RusLocale = (SUBLANG_DEFAULT shl $A) or LANG_RUSSIAN;
  965. begin
  966. Clipboard.Open;
  967. SetClipboardCodePage(RusLocale);
  968. try
  969. Clipboard.AsText := Value;
  970. finally
  971. SetClipboardCodePage(RusLocale);
  972. Clipboard.Close;
  973. end;
  974. end;
  975. procedure TGLSCustomMemo.CopyToClipBoard;
  976. begin
  977. CopyStringToClipboard(GetSelText);
  978. end;
  979. //--------------------------------------------------------------
  980. // PASTE FROM CLIPBOARD
  981. //--------------------------------------------------------------
  982. procedure TGLSCustomMemo.PasteFromClipBoard;
  983. var
  984. H, len: integer;
  985. Buff: string;
  986. begin
  987. H := ClipBoard.GetAsHandle(CF_TEXT);
  988. len := GlobalSize(H);
  989. if len = 0 then
  990. Exit;
  991. SetLength(Buff, len);
  992. SetLength(Buff, ClipBoard.GetTextBuf(PChar(Buff), len));
  993. AdjustLineBreaks(Buff);
  994. SetSelText(Buff);
  995. end;
  996. //--------------------------------------------------------------
  997. // DELETE SELECTION
  998. //--------------------------------------------------------------
  999. procedure TGLSCustomMemo.DeleteSelection(bRepaint: Boolean);
  1000. var
  1001. xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
  1002. i, len: integer;
  1003. OldX, OldY: integer;
  1004. S1, S2, S, AddSpaces: string;
  1005. Undo: TGLSMemoDeleteBufUndo;
  1006. begin
  1007. if (FSelStartY = FSelEndY) and (FSelStartX = FSelEndX) then
  1008. Exit;
  1009. OldX := CurX;
  1010. OldY := CurY;
  1011. xSelStartX := FSelStartX;
  1012. xSelStartY := FSelStartY;
  1013. xSelEndX := FSelEndX;
  1014. xSelEndY := FSelEndY;
  1015. OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
  1016. if xSelStartY = xSelEndY then
  1017. begin
  1018. S1 := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX);
  1019. S2 := '';
  1020. AddSpaces := '';
  1021. end
  1022. else
  1023. begin
  1024. len := Length(Lines[xSelStartY]);
  1025. S1 := Copy(Lines[xSelStartY], xSelStartX + 1, len);
  1026. AddSpaces := StringOfChar(' ', xSelStartX - len);
  1027. S2 := Copy(Lines[xSelEndY], 1, xSelEndX);
  1028. end;
  1029. Lines[xSelStartY] := Copy(Lines[xSelStartY], 1, xSelStartX) + AddSpaces +
  1030. Copy(Lines[xSelEndY], xSelEndX + 1, Length(Lines[xSelEndY]));
  1031. S := S1;
  1032. for i := xSelStartY + 1 to xSelEndY do
  1033. begin
  1034. S := S + #13#10;
  1035. if i <> xSelEndY then
  1036. S := S + Lines[xSelStartY + 1];
  1037. DeleteLine(xSelStartY + 1, -1, -1, -1, -1, False);
  1038. end;
  1039. S := S + S2;
  1040. CurY := xSelStartY;
  1041. CurX := xSelStartX;
  1042. ClearSelection;
  1043. Changed(xSelStartY, -1);
  1044. SelectionChanged;
  1045. if bRepaint then
  1046. Invalidate;
  1047. Undo := TGLSMemoDeleteBufUndo.Create(OldX, OldY, CurX, CurY, S);
  1048. Undo.UndoSelStartX := xSelStartX;
  1049. Undo.UndoSelStartY := xSelStartY;
  1050. Undo.UndoSelEndX := xSelEndX;
  1051. Undo.UndoSelEndY := xSelEndY;
  1052. if Assigned(FUndoList) then
  1053. FUndoList.Add(Undo);
  1054. end;
  1055. //--------------------------------------------------------------
  1056. // CUT TO CLIPBOARD
  1057. //--------------------------------------------------------------
  1058. procedure TGLSCustomMemo.CutToClipBoard;
  1059. begin
  1060. ClipBoard.SetTextBuf(PChar(GetSelText));
  1061. DeleteSelection(True);
  1062. end;
  1063. //--------------------------------------------------------------
  1064. // GET SEL TEXT
  1065. //--------------------------------------------------------------
  1066. function TGLSCustomMemo.GetSelText: string;
  1067. var
  1068. i: integer;
  1069. xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
  1070. begin
  1071. Result := '';
  1072. if (FSelStartY = FSelEndY) and (FSelStartX = FSelEndX) then
  1073. Exit;
  1074. xSelStartX := FSelStartX;
  1075. xSelStartY := FSelStartY;
  1076. xSelEndX := FSelEndX;
  1077. xSelEndY := FSelEndY;
  1078. OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
  1079. if xSelStartY = xSelEndY then
  1080. Result := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX)
  1081. else
  1082. begin
  1083. Result := Copy(Lines[xSelStartY], xSelStartX + 1,
  1084. Length(Lines[xSelStartY]));
  1085. for i := xSelStartY + 1 to xSelEndY - 1 do
  1086. Result := Result + #13#10 + Lines[i];
  1087. Result := Result + #13#10 + Copy(Lines[xSelEndY], 1, xSelEndX);
  1088. end;
  1089. end;
  1090. //--------------------------------------------------------------
  1091. // GET SEL START
  1092. //--------------------------------------------------------------
  1093. function TGLSCustomMemo.GetSelStart: TPoint;
  1094. var
  1095. xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
  1096. begin
  1097. xSelStartX := FSelStartX;
  1098. xSelStartY := FSelStartY;
  1099. xSelEndX := FSelEndX;
  1100. xSelEndY := FSelEndY;
  1101. OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
  1102. Result := Point(xSelStartX, xSelStartY);
  1103. end;
  1104. //--------------------------------------------------------------
  1105. // GET SEL END
  1106. //--------------------------------------------------------------
  1107. function TGLSCustomMemo.GetSelEnd: TPoint;
  1108. var
  1109. xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
  1110. begin
  1111. xSelStartX := FSelStartX;
  1112. xSelStartY := FSelStartY;
  1113. xSelEndX := FSelEndX;
  1114. xSelEndY := FSelEndY;
  1115. OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
  1116. Result := Point(xSelEndX, xSelEndY);
  1117. end;
  1118. //--------------------------------------------------------------
  1119. // SET SEL TEXT
  1120. //--------------------------------------------------------------
  1121. procedure TGLSCustomMemo.SetSelText(const AValue: string);
  1122. var
  1123. i, k: integer;
  1124. xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
  1125. Buff, S: string;
  1126. OldX, OldY: integer;
  1127. begin
  1128. Buff := AValue;
  1129. xSelStartX := FSelStartX;
  1130. xSelStartY := FSelStartY;
  1131. xSelEndX := FSelEndX;
  1132. xSelEndY := FSelEndY;
  1133. OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
  1134. DeleteSelection(False);
  1135. OldX := CurX;
  1136. OldY := CurY;
  1137. i := Pos(#13#10, Buff);
  1138. S := Lines[xSelStartY];
  1139. if i = 0 then
  1140. begin
  1141. Lines[xSelStartY] := Copy(S, 1, xSelStartX) + Buff
  1142. + Copy(S, xSelStartX + 1, Length(S));
  1143. CurX := xSelStartX;
  1144. if Buff <> '' then
  1145. CurX := CurX + Length(Buff);
  1146. end
  1147. else
  1148. begin
  1149. k := xSelStartY;
  1150. Lines[k] := Copy(S, 1, xSelStartX) + Copy(Buff, 1, i - 1);
  1151. TGLSMemoStrings(Lines).DoInsert(k + 1, Copy(S, xSelStartX + 1, Length(S)));
  1152. while True do
  1153. begin
  1154. Buff := Copy(Buff, i + 2, Length(Buff));
  1155. i := Pos(#13#10, Buff);
  1156. k := k + 1;
  1157. if i = 0 then
  1158. break;
  1159. TGLSMemoStrings(Lines).DoInsert(k, Copy(Buff, 1, i - 1));
  1160. end;
  1161. Lines[k] := Buff + Lines[k];
  1162. CurY := k;
  1163. CurX := Length(Buff);
  1164. end;
  1165. ClearSelection;
  1166. Changed(xSelStartY, -1);
  1167. if Assigned(FUndoList) then
  1168. FUndoList.Add(TGLSMemoPasteUndo.Create(OldX, OldY, CurX, CurY, AValue));
  1169. Invalidate;
  1170. end;
  1171. //--------------------------------------------------------------
  1172. // GET SEL LENGTH
  1173. //--------------------------------------------------------------
  1174. function TGLSCustomMemo.GetSelLength: integer;
  1175. begin
  1176. Result := Length(GetSelText);
  1177. end;
  1178. //--------------------------------------------------------------
  1179. // CHANGED
  1180. //--------------------------------------------------------------
  1181. procedure TGLSCustomMemo.Changed(FromLine, ToLine: integer);
  1182. var
  1183. i: integer;
  1184. begin
  1185. if ToLine < FromLine then
  1186. ToLine := Lines.Count - 1;
  1187. for i := FromLine to ToLine do
  1188. ValidAttrs[i] := False;
  1189. InvalidateLineRange(FromLine, ToLine);
  1190. if Assigned(FOnChange) then
  1191. FOnChange(Self);
  1192. end;
  1193. //--------------------------------------------------------------
  1194. // ATTR CHANGED
  1195. //--------------------------------------------------------------
  1196. procedure TGLSCustomMemo.AttrChanged(LineNo: integer);
  1197. begin
  1198. ValidAttrs[LineNo] := False;
  1199. InvalidateLineRange(LineNo, LineNo);
  1200. if Assigned(FOnAttrChange) then
  1201. FOnAttrChange(Self);
  1202. end;
  1203. //--------------------------------------------------------------
  1204. // SELECTION CHANGED
  1205. //--------------------------------------------------------------
  1206. procedure TGLSCustomMemo.SelectionChanged;
  1207. begin
  1208. if Assigned(FOnSelectionChange) then
  1209. FOnSelectionChange(Self);
  1210. end;
  1211. //--------------------------------------------------------------
  1212. // STATUS CHANGED
  1213. //--------------------------------------------------------------
  1214. procedure TGLSCustomMemo.StatusChanged;
  1215. begin
  1216. if Assigned(FOnStatusChange) then
  1217. FOnStatusChange(Self);
  1218. end;
  1219. //--------------------------------------------------------------
  1220. // CLEAR SELECTION
  1221. //--------------------------------------------------------------
  1222. procedure TGLSCustomMemo.ClearSelection;
  1223. var
  1224. rct: TRect;
  1225. Changed: Boolean;
  1226. begin
  1227. Changed := not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY));
  1228. rct := LineRangeRect(FSelStartY, FSelEndY);
  1229. FSelStartX := CurX;
  1230. FSelStartY := CurY;
  1231. FSelEndX := CurX;
  1232. FSelEndY := CurY;
  1233. FPrevSelX := CurX;
  1234. FPrevSelY := CurY;
  1235. if Changed then
  1236. begin
  1237. SelectionChanged;
  1238. InvalidateRect(Handle, @rct, true);
  1239. end;
  1240. if Assigned(FOnMoveCursor) then
  1241. FOnMoveCursor(Self);
  1242. end;
  1243. //--------------------------------------------------------------
  1244. // EXPAND SELECTION
  1245. //--------------------------------------------------------------
  1246. procedure TGLSCustomMemo.ExpandSelection;
  1247. var
  1248. rct: TRect;
  1249. begin
  1250. rct := LineRangeRect(FPrevSelY, CurY);
  1251. FSelEndX := CurX;
  1252. FSelEndY := CurY;
  1253. FPrevSelX := CurX;
  1254. FPrevSelY := CurY;
  1255. SelectionChanged;
  1256. InvalidateRect(Handle, @rct, true);
  1257. if Assigned(FOnMoveCursor) then
  1258. FOnMoveCursor(Self);
  1259. end;
  1260. //--------------------------------------------------------------
  1261. // MAX LENGTH
  1262. //--------------------------------------------------------------
  1263. function TGLSCustomMemo.MaxLength: integer;
  1264. var
  1265. i, len: integer;
  1266. begin
  1267. Result := 0;
  1268. for i := 0 to Lines.Count - 1 do
  1269. begin
  1270. len := Length(Lines[i]);
  1271. if len > Result then
  1272. Result := len;
  1273. end;
  1274. end;
  1275. //--------------------------------------------------------------
  1276. // DO SCROLL
  1277. //--------------------------------------------------------------
  1278. procedure TGLSCustomMemo.DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
  1279. var
  1280. eRect, scrRect, sbRect: TRect;
  1281. Old: integer;
  1282. begin
  1283. eRect := EditorRect;
  1284. case Sender.Kind of
  1285. sbVertical:
  1286. begin
  1287. Old := FTopLine;
  1288. FTopLine := FTopLine + ByValue;
  1289. if FTopLine > Sender.MaxPosition then
  1290. FTopLine := Sender.MaxPosition;
  1291. if FTopLine < 0 then
  1292. FTopLine := 0;
  1293. if Old <> FTopLine then
  1294. begin
  1295. ShowCaret(False);
  1296. if CurY < FTopLine then
  1297. CurY := FTopLine;
  1298. if CurY > LastVisibleLine then
  1299. CurY := LastVisibleLine;
  1300. ScrollDC(Canvas.Handle, 0, (Old - FTopLine) * FCellSize.H,
  1301. eRect, eRect, 0, @scrRect);
  1302. InvalidateRect(Handle, @scrRect, True);
  1303. sbRect := Sender.FullRect;
  1304. InvalidateRect(Handle, @sbRect, True);
  1305. FGutter.Invalidate;
  1306. ShowCaret(True);
  1307. end;
  1308. end;
  1309. sbHorizontal:
  1310. begin
  1311. Old := FLeftCol;
  1312. FLeftCol := FLeftCol + ByValue;
  1313. if FLeftCol > Sender.MaxPosition then
  1314. FLeftCol := Sender.MaxPosition;
  1315. if FLeftCol < 0 then
  1316. FLeftCol := 0;
  1317. if Old <> FLeftCol then
  1318. begin
  1319. ShowCaret(False);
  1320. if CurX < FLeftCol then
  1321. CurX := FLeftCol;
  1322. if CurX > LastVisiblePos then
  1323. CurX := LastVisiblePos;
  1324. ScrollDC(Canvas.Handle, (Old - FLeftCol) * FCellSize.W, 0,
  1325. eRect, eRect, 0, @scrRect);
  1326. InvalidateRect(Handle, @scrRect, True);
  1327. sbRect := Sender.FullRect;
  1328. InvalidateRect(Handle, @sbRect, True);
  1329. ShowCaret(True);
  1330. end;
  1331. end;
  1332. end;
  1333. end;
  1334. //--------------------------------------------------------------
  1335. // DO SCROLL PAGE
  1336. //--------------------------------------------------------------
  1337. procedure TGLSCustomMemo.DoScrollPage(Sender: TGLSMemoScrollBar; ByValue:
  1338. integer);
  1339. begin
  1340. case Sender.Kind of
  1341. sbVertical: DoScroll(Sender, ByValue * VisibleLineCount);
  1342. sbHorizontal: DoScroll(Sender, ByValue * VisiblePosCount);
  1343. end;
  1344. end;
  1345. //--------------------------------------------------------------
  1346. // SET LINES
  1347. //--------------------------------------------------------------
  1348. procedure TGLSCustomMemo.SetLines(ALines: TStrings);
  1349. begin
  1350. if ALines <> nil then
  1351. begin
  1352. FLines.Assign(ALines);
  1353. Changed(0, -1);
  1354. SelectionChanged;
  1355. Invalidate;
  1356. end;
  1357. end;
  1358. //--------------------------------------------------------------
  1359. // SET/GET LINE STYLE
  1360. //--------------------------------------------------------------
  1361. procedure TGLSCustomMemo.SetLineStyle(Index: integer; Value: integer);
  1362. begin
  1363. TGLSMemoStrings(FLines).Style[Index] := Value;
  1364. if IsLineVisible(Index) then
  1365. AttrChanged(Index);
  1366. end;
  1367. function TGLSCustomMemo.GetLineStyle(Index: integer): integer;
  1368. begin
  1369. Result := TGLSMemoStrings(FLines).Style[Index];
  1370. end;
  1371. //--------------------------------------------------------------
  1372. // GET/SET IN COMMENT
  1373. //--------------------------------------------------------------
  1374. function TGLSCustomMemo.GetInComment(Index: integer): Boolean;
  1375. begin
  1376. Result := TGLSMemoStrings(FLines).InComment[Index];
  1377. end;
  1378. procedure TGLSCustomMemo.SetInComment(Index: integer; Value: Boolean);
  1379. begin
  1380. TGLSMemoStrings(FLines).InComment[Index] := Value;
  1381. end;
  1382. //--------------------------------------------------------------
  1383. // GET/SET IN BRACKETS
  1384. //--------------------------------------------------------------
  1385. function TGLSCustomMemo.GetInBrackets(Index: integer): integer;
  1386. begin
  1387. Result := TGLSMemoStrings(FLines).InBrackets[Index];
  1388. end;
  1389. procedure TGLSCustomMemo.SetInBrackets(Index: integer; Value: integer);
  1390. begin
  1391. TGLSMemoStrings(FLines).InBrackets[Index] := Value;
  1392. end;
  1393. //--------------------------------------------------------------
  1394. // GET/SET VALID ATTRS
  1395. //--------------------------------------------------------------
  1396. function TGLSCustomMemo.GetValidAttrs(Index: integer): Boolean;
  1397. begin
  1398. Result := TGLSMemoStrings(FLines).ValidAttrs[Index];
  1399. end;
  1400. procedure TGLSCustomMemo.SetValidAttrs(Index: integer; Value: Boolean);
  1401. begin
  1402. TGLSMemoStrings(FLines).ValidAttrs[Index] := Value;
  1403. end;
  1404. //--------------------------------------------------------------
  1405. // GET/SET CHAR ATTRS
  1406. //--------------------------------------------------------------
  1407. function TGLSCustomMemo.GetCharAttrs(Index: integer): string;
  1408. begin
  1409. Result := TGLSMemoStrings(FLines).CharAttrs[Index];
  1410. end;
  1411. procedure TGLSCustomMemo.SetCharAttrs(Index: integer; const Value: string);
  1412. begin
  1413. TGLSMemoStrings(FLines).CharAttrs[Index] := Value;
  1414. if IsLineVisible(Index) then
  1415. AttrChanged(Index);
  1416. end;
  1417. //--------------------------------------------------------------
  1418. // SET CUR X
  1419. //--------------------------------------------------------------
  1420. procedure TGLSCustomMemo.SetCurX(Value: integer);
  1421. var
  1422. len: integer;
  1423. WasVisible: Boolean;
  1424. begin
  1425. if Value < 0 then
  1426. if CurY = 0 then
  1427. Value := 0
  1428. else
  1429. begin
  1430. CurY := CurY - 1;
  1431. Value := Length(Lines[CurY]);
  1432. end;
  1433. if (CurY >= 0) and (CurY < Lines.Count) then
  1434. begin
  1435. len := Length(Lines[CurY]);
  1436. if Value > len then
  1437. begin
  1438. Lines[CurY] := Lines[CurY] + StringOfChar(' ', Value - len);
  1439. // Value := len;
  1440. ValidAttrs[CurY] := False;
  1441. InvalidateLineRange(CurY, CurY);
  1442. end;
  1443. end;
  1444. FCurX := Value;
  1445. WasVisible := FCaretVisible;
  1446. if WasVisible then
  1447. ShowCaret(False);
  1448. MakeVisible;
  1449. ResizeScrollBars;
  1450. StatusChanged;
  1451. if WasVisible then
  1452. ShowCaret(True);
  1453. end;
  1454. //--------------------------------------------------------------
  1455. // SET CUR Y
  1456. //--------------------------------------------------------------
  1457. procedure TGLSCustomMemo.SetCurY(Value: integer);
  1458. var
  1459. Old: integer;
  1460. WasVisible: Boolean;
  1461. begin
  1462. WasVisible := FCaretVisible;
  1463. if WasVisible then
  1464. ShowCaret(False);
  1465. Old := CurY;
  1466. if Value < 0 then
  1467. Value := 0;
  1468. if Value >= Lines.Count then
  1469. Value := Lines.Count - 1;
  1470. FCurY := Value;
  1471. if (CurY <> Old) and (Old >= 0) and (Old < Lines.Count) then
  1472. Lines[Old] := TrimRight(Lines[Old]);
  1473. CurX := CurX;
  1474. MakeVisible;
  1475. ResizeScrollBars;
  1476. StatusChanged;
  1477. if WasVisible then
  1478. ShowCaret(True);
  1479. end;
  1480. //--------------------------------------------------------------
  1481. // MOVE CURSOR
  1482. //--------------------------------------------------------------
  1483. procedure TGLSCustomMemo.MoveCursor(dX, dY: integer; Shift: TShiftState);
  1484. var
  1485. Selecting: Boolean;
  1486. //------------------------------------------------------------
  1487. function IsDelimiter(c: char): Boolean;
  1488. begin
  1489. Result := Pos(c, ' .,;:/?!@#$%^&*(){}[]<>-+=|\') > 0;
  1490. end;
  1491. //------------------------------------------------------------
  1492. function IsStopChar(c, cThis: char): Boolean;
  1493. begin
  1494. Result := IsDelimiter(c) <> IsDelimiter(cThis);
  1495. end;
  1496. //------------------------------------------------------------
  1497. procedure MoveWordLeft;
  1498. var
  1499. S: string;
  1500. begin
  1501. CurX := CurX - 1;
  1502. S := TrimRight(Lines[CurY]);
  1503. while CurX > 0 do
  1504. begin
  1505. if IsStopChar(S[CurX], S[CurX + 1]) then
  1506. break;
  1507. CurX := CurX - 1;
  1508. end;
  1509. if (CurX < 0) then
  1510. if CurY > 0 then
  1511. begin
  1512. CurY := CurY - 1;
  1513. CurX := Length(Lines[CurY]);
  1514. end;
  1515. end;
  1516. //------------------------------------------------------------
  1517. procedure MoveWordRight;
  1518. var
  1519. Len: integer;
  1520. S: string;
  1521. begin
  1522. S := TrimRight(Lines[CurY]);
  1523. Len := Length(S);
  1524. CurX := CurX + 1;
  1525. while CurX < Len do
  1526. begin
  1527. if IsStopChar(S[CurX + 1], S[CurX]) then
  1528. break;
  1529. CurX := CurX + 1;
  1530. end;
  1531. if CurX > Len then
  1532. if CurY < Lines.Count - 1 then
  1533. begin
  1534. CurY := CurY + 1;
  1535. CurX := 0;
  1536. end;
  1537. end;
  1538. //------------------------------------------------------------
  1539. begin
  1540. Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
  1541. and (CurY = FPrevSelY);
  1542. if ssCtrl in Shift then
  1543. begin
  1544. if dX > 0 then
  1545. MoveWordRight;
  1546. if dX < 0 then
  1547. MoveWordLeft;
  1548. end
  1549. else
  1550. begin
  1551. CurY := CurY + dY;
  1552. CurX := CurX + dX;
  1553. end;
  1554. if Selecting then
  1555. ExpandSelection
  1556. else
  1557. ClearSelection;
  1558. end;
  1559. //--------------------------------------------------------------
  1560. // MOVE PAGE
  1561. //--------------------------------------------------------------
  1562. procedure TGLSCustomMemo.MovePage(dP: integer; Shift: TShiftState);
  1563. var
  1564. eRect: TRect;
  1565. LinesPerPage: integer;
  1566. Selecting: Boolean;
  1567. begin
  1568. if FCellSize.H = 0 then
  1569. Exit;
  1570. Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
  1571. and (CurY = FPrevSelY);
  1572. eRect := EditorRect;
  1573. LinesPerPage := (eRect.Bottom - eRect.Top) div FCellSize.H - 1;
  1574. CurY := CurY + dP * LinesPerPage;
  1575. if ssCtrl in Shift then
  1576. if dP > 0 then
  1577. begin
  1578. CurY := Lines.Count - 1;
  1579. CurX := Length(Lines[Lines.Count - 1]);
  1580. end
  1581. else
  1582. begin
  1583. CurY := 0;
  1584. CurX := 0;
  1585. end;
  1586. if Selecting then
  1587. ExpandSelection
  1588. else
  1589. ClearSelection;
  1590. end;
  1591. //--------------------------------------------------------------
  1592. // GO HOME
  1593. //--------------------------------------------------------------
  1594. procedure TGLSCustomMemo.GoHome(Shift: TShiftState);
  1595. var
  1596. Selecting: Boolean;
  1597. begin
  1598. Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
  1599. and (CurY = FPrevSelY);
  1600. CurX := 0;
  1601. FLeftCol := 0;
  1602. if Selecting then
  1603. ExpandSelection
  1604. else
  1605. ClearSelection;
  1606. end;
  1607. //--------------------------------------------------------------
  1608. // GO END
  1609. //--------------------------------------------------------------
  1610. procedure TGLSCustomMemo.GoEnd(Shift: TShiftState);
  1611. var
  1612. Selecting: Boolean;
  1613. S, S1: string;
  1614. begin
  1615. Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
  1616. and (CurY = FPrevSelY);
  1617. S := Lines[CurY];
  1618. if not Selecting then
  1619. S := TrimRight(S);
  1620. S1 := TrimRight(Copy(S, CurX + 1, Length(S)));
  1621. S := Copy(S, 1, CurX);
  1622. Lines[CurY] := S + S1;
  1623. CurX := Length(Lines[CurY]);
  1624. if Selecting then
  1625. ExpandSelection
  1626. else
  1627. ClearSelection;
  1628. end;
  1629. //--------------------------------------------------------------
  1630. // INSERT CHAR
  1631. //--------------------------------------------------------------
  1632. procedure TGLSCustomMemo.InsertChar(C: Char);
  1633. var
  1634. S, S1: string;
  1635. NewPlace: integer;
  1636. rct: TRect;
  1637. CurX0, CurY0: integer;
  1638. begin
  1639. CurX0 := CurX;
  1640. CurY0 := CurY;
  1641. S := Lines[CurY];
  1642. NewPlace := CurX + 1;
  1643. if C = #9 then
  1644. begin
  1645. while (NewPlace mod TabSize) <> 0 do
  1646. Inc(NewPlace);
  1647. S1 := StringOfChar(' ', NewPlace - CurX);
  1648. end
  1649. else
  1650. S1 := C;
  1651. Insert(S1, S, CurX + 1);
  1652. Lines[CurY] := S;
  1653. CurX := NewPlace;
  1654. ClearSelection;
  1655. rct := LineRect(CurY);
  1656. Changed(CurY, CurY);
  1657. if Assigned(FUndoList) then
  1658. FUndoList.Add(TGLSMemoInsCharUndo.Create(CurX0, CurY0, CurX, CurY, S1));
  1659. InvalidateRect(Handle, @rct, True);
  1660. end;
  1661. //--------------------------------------------------------------
  1662. // INSERT TEMPLATE
  1663. //--------------------------------------------------------------
  1664. procedure TGLSCustomMemo.InsertTemplate(AText: string);
  1665. var
  1666. i, NewCurX, NewCurY: integer;
  1667. Indent: string;
  1668. FoundCursor: Boolean;
  1669. begin
  1670. Indent := IndentCurrLine;
  1671. DeleteSelection(False);
  1672. ClearSelection;
  1673. NewCurX := CurX;
  1674. NewCurY := CurY;
  1675. FoundCursor := False;
  1676. i := 1;
  1677. while i <= Length(AText) do
  1678. begin
  1679. if AText[i] = #13 then
  1680. begin
  1681. if (i = Length(AText)) or (AText[i + 1] <> #10) then
  1682. Insert(#10 + Indent, AText, i + 1);
  1683. if not FoundCursor then
  1684. begin
  1685. Inc(NewCurY);
  1686. NewCurX := Length(Indent);
  1687. end;
  1688. Inc(i, 1 + Length(Indent));
  1689. end
  1690. else if AText[i] = #7 then
  1691. begin
  1692. FoundCursor := True;
  1693. Delete(AText, i, 1);
  1694. Dec(i);
  1695. end
  1696. else if Ord(AText[i]) < Ord(' ') then
  1697. begin
  1698. Delete(AText, i, 1);
  1699. Dec(i);
  1700. end
  1701. else if not FoundCursor then
  1702. Inc(NewCurX);
  1703. Inc(i);
  1704. end;
  1705. SetSelText(AText);
  1706. SetCursor(NewCurX, NewCurY);
  1707. ClearSelection;
  1708. try
  1709. SetFocus;
  1710. except
  1711. end;
  1712. end;
  1713. //--------------------------------------------------------------
  1714. // DELETE CHAR
  1715. //--------------------------------------------------------------
  1716. procedure TGLSCustomMemo.DeleteChar(OldX, OldY: integer);
  1717. var
  1718. S, S1: string;
  1719. rct: TRect;
  1720. C: char;
  1721. Undo: TGLSMemoDelCharUndo;
  1722. IsBackspace: Boolean;
  1723. begin
  1724. if FReadOnly then
  1725. Exit;
  1726. if OldX < 0 then
  1727. begin
  1728. OldX := CurX;
  1729. OldY := CurY;
  1730. IsBackspace := False;
  1731. end
  1732. else
  1733. IsBackspace := True;
  1734. ClearSelection;
  1735. S := Lines[CurY];
  1736. S1 := Copy(S, CurX + 1, Length(S));
  1737. if not IsBackspace then
  1738. S1 := TrimRight(S1);
  1739. S := Copy(S, 1, CurX);
  1740. Lines[CurY] := S + S1;
  1741. if CurX < Length(Lines[CurY]) then
  1742. begin
  1743. S := Lines[CurY];
  1744. C := S[CurX + 1];
  1745. Delete(S, CurX + 1, 1);
  1746. Lines[CurY] := S;
  1747. Changed(CurY, CurY);
  1748. rct := LineRect(CurY);
  1749. Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, C);
  1750. Undo.IsBackSpace := IsBackSpace;
  1751. if Assigned(FUndoList) then
  1752. FUndoList.Add(Undo);
  1753. end
  1754. else if CurY < Lines.Count - 1 then
  1755. begin
  1756. S := Lines[CurY] + Lines[CurY + 1];
  1757. Lines[CurY] := S;
  1758. DeleteLine(CurY + 1, OldX, OldY, CurX, CurY, False);
  1759. Changed(CurY, -1);
  1760. rct := EditorRect;
  1761. Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, #13);
  1762. Undo.IsBackSpace := IsBackSpace;
  1763. if Assigned(FUndoList) then
  1764. FUndoList.Add(Undo);
  1765. end;
  1766. ClearSelection;
  1767. InvalidateRect(Handle, @rct, True);
  1768. end;
  1769. //--------------------------------------------------------------
  1770. // DELETE LINE
  1771. //--------------------------------------------------------------
  1772. procedure TGLSCustomMemo.DeleteLine(Index, OldX, OldY, NewX, NewY: integer;
  1773. FixUndo: Boolean);
  1774. var
  1775. rct: TRect;
  1776. s: string;
  1777. begin
  1778. if Index < 0 then
  1779. Index := CurY;
  1780. if OldX < 0 then
  1781. begin
  1782. OldX := CurX;
  1783. OldY := CurY;
  1784. end;
  1785. s := Lines[Index];
  1786. TGLSMemoStrings(Lines).FDeleting := True;
  1787. if Lines.Count = 1 then
  1788. TGLSMemoStrings(Lines)[0] := ''
  1789. else
  1790. Lines.Delete(Index);
  1791. TGLSMemoStrings(Lines).FDeleting := False;
  1792. ClearSelection;
  1793. if Index >= Lines.Count then
  1794. Changed(Index - 1, -1)
  1795. else
  1796. Changed(Index, -1);
  1797. rct := EditorRect;
  1798. InvalidateRect(Handle, @rct, True);
  1799. if NewX < 0 then
  1800. begin
  1801. if Length(Lines[0]) < CurX then
  1802. CurX := Length(Lines[0]);
  1803. if Index >= Lines.Count then
  1804. CurY := Index - 1
  1805. else
  1806. CurY := Index;
  1807. NewX := CurX;
  1808. NewY := CurY;
  1809. end
  1810. else
  1811. begin
  1812. CurX := NewX;
  1813. CurY := NewY;
  1814. end;
  1815. if Assigned(FUndoList) and FixUndo then
  1816. FUndoList.Add(TGLSMEmoDelLineUndo.Create(Index, OldX, OldY, NewX, NewY, s));
  1817. end;
  1818. //--------------------------------------------------------------
  1819. // BACK SPACE
  1820. //--------------------------------------------------------------
  1821. procedure TGLSCustomMemo.BackSpace;
  1822. var
  1823. OldX, OldY: integer;
  1824. begin
  1825. OldX := CurX;
  1826. OldY := CurY;
  1827. MoveCursor(-1, 0, []);
  1828. if (OldX = CurX) and (OldY = CurY) then
  1829. Exit;
  1830. DeleteChar(OldX, OldY);
  1831. end;
  1832. //--------------------------------------------------------------
  1833. // BACK SPACE WORD
  1834. //--------------------------------------------------------------
  1835. procedure TGLSCustomMemo.BackSpaceWord;
  1836. begin
  1837. ClearSelection;
  1838. MoveCursor(-1, 0, [ssShift, ssCtrl]);
  1839. DeleteSelection(True);
  1840. end;
  1841. //--------------------------------------------------------------
  1842. // INDENT CURR LINE
  1843. //--------------------------------------------------------------
  1844. function TGLSCustomMemo.IndentCurrLine: string;
  1845. var
  1846. Len, Count: integer;
  1847. CurS: string;
  1848. begin
  1849. Result := '';
  1850. if not AutoIndent then
  1851. Exit;
  1852. CurS := Lines[CurY];
  1853. Len := Length(CurS);
  1854. Count := 0;
  1855. while (Count < CurX) and (Count < Len) do
  1856. begin
  1857. if CurS[Count + 1] <> ' ' then
  1858. break;
  1859. Inc(Count);
  1860. end;
  1861. Result := StringOfChar(' ', Count);
  1862. end;
  1863. //--------------------------------------------------------------
  1864. // NEW LINE
  1865. //--------------------------------------------------------------
  1866. procedure TGLSCustomMemo.NewLine;
  1867. var
  1868. S, sIndent: string;
  1869. OldX, OldY: integer;
  1870. begin
  1871. OldX := CurX;
  1872. OldY := CurY;
  1873. S := Lines[CurY];
  1874. sIndent := IndentCurrLine;
  1875. Lines[CurY] := Copy(S, 1, CurX);
  1876. S := TrimRight(Copy(S, CurX + 1, Length(S)));
  1877. if AutoIndent then
  1878. while (Length(S) > 0) and (S[1] = ' ') do
  1879. Delete(S, 1, 1);
  1880. TGLSMemoStrings(Lines).DoInsert(CurY + 1, sIndent + S);
  1881. GoHome([]);
  1882. MoveCursor(0, 1, []);
  1883. CurX := Length(sIndent);
  1884. ClearSelection;
  1885. if Assigned(FUndoList) then
  1886. FUndoList.Add(TGLSMemoInsCharUndo.Create(OldX, OldY, CurX, CurY, #13 +
  1887. sIndent));
  1888. Invalidate;
  1889. Changed(CurY - 1, -1);
  1890. end;
  1891. //--------------------------------------------------------------
  1892. // ADD STRING
  1893. //--------------------------------------------------------------
  1894. function TGLSCustomMemo.AddString(const S: string): integer;
  1895. begin
  1896. if Lines.Count = 0 then
  1897. TGLSMemoStrings(Lines).DoAdd('');
  1898. MovePage(1, [ssCtrl]); // end of text
  1899. if not ((Lines.Count = 1) and (Lines[0] = '')) then
  1900. begin
  1901. TGLSMemoStrings(Lines).DoAdd('');
  1902. CurX := 0;
  1903. CurY := Lines.Count;
  1904. ClearSelection;
  1905. // S := #13#10 + S;
  1906. end;
  1907. SetSelText(S);
  1908. Result := Lines.Count - 1;
  1909. end;
  1910. //--------------------------------------------------------------
  1911. // INSERT STRING
  1912. //--------------------------------------------------------------
  1913. procedure TGLSCustomMemo.InsertString(Index: integer; S: string);
  1914. begin
  1915. CurY := Index;
  1916. CurX := 0;
  1917. ClearSelection;
  1918. if not ((Lines.Count = 1) and (Lines[0] = '')) then
  1919. S := S + #13#10;
  1920. SetSelText(S);
  1921. end;
  1922. //--------------------------------------------------------------
  1923. // DO COMMAND
  1924. //--------------------------------------------------------------
  1925. procedure TGLSCustomMemo.DoCommand(cmd: TCommand; const AShift: TShiftState);
  1926. begin
  1927. case cmd of
  1928. cmDelete: if not FReadOnly then
  1929. begin
  1930. if ssShift in AShift then
  1931. CutToClipboard
  1932. else if FDelErase and
  1933. (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY))) then
  1934. DeleteSelection(True)
  1935. else
  1936. DeleteChar(-1, -1);
  1937. end;
  1938. cmBackSpace: BackSpace;
  1939. cmWordBackSpace: BackSpaceWord;
  1940. cmNewLine: NewLine;
  1941. cmDelLine: DeleteLine(-1, -1, -1, -1, -1, True);
  1942. cmCopy: CopyToClipboard;
  1943. cmCut: CutToClipboard;
  1944. cmPaste: PasteFromClipboard;
  1945. cmHome: GoHome(AShift);
  1946. cmEnd: GoEnd(AShift);
  1947. cmPageDown: MovePage(1, AShift);
  1948. cmPageUp: MovePage(-1, AShift);
  1949. cmInsert:
  1950. begin
  1951. if ssShift in AShift then
  1952. PasteFromClipboard;
  1953. if ssCtrl in AShift then
  1954. CopyToClipboard;
  1955. end;
  1956. end;
  1957. end;
  1958. //--------------------------------------------------------------
  1959. // KEY DOWN
  1960. //--------------------------------------------------------------
  1961. procedure TGLSCustomMemo.KeyDown(var Key: Word; Shift: TShiftState);
  1962. begin
  1963. ShowCaret(False);
  1964. inherited;
  1965. case Key of
  1966. VK_LEFT: MoveCursor(-1, 0, Shift);
  1967. VK_RIGHT: MoveCursor(1, 0, Shift);
  1968. VK_UP: MoveCursor(0, -1, Shift);
  1969. VK_DOWN: MoveCursor(0, 1, Shift);
  1970. VK_HOME, VK_END,
  1971. VK_DELETE: DoCommand(Key, Shift);
  1972. VK_PRIOR, VK_NEXT:
  1973. DoCommand(Key, Shift);
  1974. VK_INSERT: DoCommand(Key, Shift);
  1975. end;
  1976. ShowCaret(True);
  1977. end;
  1978. //--------------------------------------------------------------
  1979. // KEY PRESS
  1980. //--------------------------------------------------------------
  1981. procedure TGLSCustomMemo.KeyPress(var Key: Char);
  1982. begin
  1983. if FReadOnly then
  1984. Exit;
  1985. ShowCaret(False);
  1986. inherited;
  1987. if (ord(Key) in [9, 32..255]) and (ord(Key) <> 127) then
  1988. begin
  1989. if FDelErase and (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY)))
  1990. then
  1991. DeleteSelection(True);
  1992. InsertChar(Key);
  1993. end
  1994. else
  1995. DoCommand(Ord(Key), []);
  1996. ShowCaret(True);
  1997. end;
  1998. //--------------------------------------------------------------
  1999. // MOUSE DOWN
  2000. //--------------------------------------------------------------
  2001. procedure TGLSCustomMemo.MouseDown(Button: TMouseButton; Shift: TShiftState;
  2002. X, Y: Integer);
  2003. var
  2004. newPos: TCellPos;
  2005. charPos: TFullPos;
  2006. Selecting: Boolean;
  2007. begin
  2008. inherited;
  2009. if not Focused then
  2010. begin
  2011. SetFocus;
  2012. // Exit;
  2013. end;
  2014. if FAfterDoubleClick then
  2015. begin
  2016. FAfterDoubleClick := False;
  2017. Exit;
  2018. end;
  2019. if Button <>mbLeft then
  2020. Exit;
  2021. if sbVert.MouseDown(Button, Shift, X, Y) then
  2022. Exit;
  2023. if sbHorz.MouseDown(Button, Shift, X, Y) then
  2024. Exit;
  2025. if PointInRect(Point(X, Y), EditorRect) then
  2026. begin
  2027. ShowCaret(False);
  2028. newPos := CellFromPos(X, Y);
  2029. CurY := newPos.Y + FTopLine;
  2030. CurX := newPos.X + FLeftCol;
  2031. if Assigned(FOnMoveCursor) then
  2032. FOnMoveCursor(Self);
  2033. Selecting := ssShift in Shift;
  2034. if Button = mbLeft then
  2035. begin
  2036. if Selecting then
  2037. ExpandSelection
  2038. else
  2039. ClearSelection;
  2040. FLeftButtonDown := True;
  2041. end
  2042. else
  2043. ShowCaret(True);
  2044. end;
  2045. if Assigned(FOnGutterClick) then
  2046. if PointInRect(Point(X, Y), FGutter.FullRect) then
  2047. begin
  2048. charPos := CharFromPos(X, Y);
  2049. if charPos.LineNo < Lines.Count then
  2050. FOnGutterClick(Self, charPos.LineNo);
  2051. end;
  2052. end;
  2053. //--------------------------------------------------------------
  2054. // MOUSE MOVE
  2055. //--------------------------------------------------------------
  2056. procedure TGLSCustomMemo.MouseMove(Shift: TShiftState; X, Y: Integer);
  2057. var
  2058. newPos: TCellPos;
  2059. begin
  2060. inherited;
  2061. if sbVert.MouseMove(Shift, X, Y) then
  2062. Exit;
  2063. if sbHorz.MouseMove(Shift, X, Y) then
  2064. Exit;
  2065. if PointInRect(Point(X, Y), EditorRect) then
  2066. begin
  2067. if (ssLeft in Shift) and FLeftButtonDown then
  2068. begin
  2069. newPos := CellFromPos(X, Y);
  2070. CurY := newPos.Y + FTopLine;
  2071. CurX := newPos.X + FLeftCol;
  2072. ExpandSelection;
  2073. end;
  2074. end
  2075. end;
  2076. //--------------------------------------------------------------
  2077. // MOUSE UP
  2078. //--------------------------------------------------------------
  2079. procedure TGLSCustomMemo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y:
  2080. Integer);
  2081. begin
  2082. inherited;
  2083. if sbVert.MouseUp(Button, Shift, X, Y) then
  2084. Exit;
  2085. if sbHorz.MouseUp(Button, Shift, X, Y) then
  2086. Exit;
  2087. if Button = mbLeft then
  2088. ShowCaret(True);
  2089. FLeftButtonDown := False;
  2090. FLastMouseUpX := X;
  2091. FLastMouseUpY := Y;
  2092. end;
  2093. //--------------------------------------------------------------
  2094. // DBL CLICK
  2095. //--------------------------------------------------------------
  2096. procedure TGLSCustomMemo.DblClick;
  2097. var
  2098. clickPos: TCellPos;
  2099. clickX, clickY: integer;
  2100. //------------------------------------------------------------
  2101. // SELECT WORD
  2102. //------------------------------------------------------------
  2103. procedure SelectWord;
  2104. const
  2105. stopChars: TSysCharSet = [' ', ';', '.', ',', ':', '?', '!', '''', '"',
  2106. '<', '>', '/', '*', '+', '-', '=', '(', ')',
  2107. '[', ']', '{', '}', '@', '#', '$', '%', '^',
  2108. '&', '|', '\'];
  2109. var
  2110. s: string;
  2111. i: integer;
  2112. rct: TRect;
  2113. begin
  2114. CurX := clickX;
  2115. CurY := clickY;
  2116. if (CurX = clickX) and (CurY = clickY) then
  2117. begin
  2118. s := Lines[clickY];
  2119. if s[clickX + 1] = ' ' then
  2120. Exit;
  2121. i := clickX;
  2122. while (i >= 0) and not CharInSet(s[i + 1], stopChars) do
  2123. Dec(i);
  2124. FSelStartY := clickY;
  2125. FSelStartX := i + 1;
  2126. i := clickX;
  2127. while (i < Length(s)) and not CharInSet(s[i + 1], stopChars) do
  2128. Inc(i);
  2129. FSelEndY := clickY;
  2130. FSelEndX := i;
  2131. if FSelEndX <> FSelStartX then
  2132. begin
  2133. FAfterDoubleClick := True;
  2134. rct := LineRangeRect(CurY, CurY);
  2135. SelectionChanged;
  2136. InvalidateRect(Handle, @rct, true);
  2137. end;
  2138. end;
  2139. end;
  2140. //------------------------------------------------------------
  2141. begin
  2142. if PointInRect(Point(FLastMouseUpX, FLastMouseUpY), EditorRect) then
  2143. begin
  2144. clickPos := CellFromPos(FLastMouseUpX, FLastMouseUpY);
  2145. clickX := clickPos.X + FLeftCol;
  2146. clickY := clickPos.Y + FTopLine;
  2147. SelectWord;
  2148. end;
  2149. inherited;
  2150. end;
  2151. //--------------------------------------------------------------
  2152. // WM_GETDLGCODE
  2153. //--------------------------------------------------------------
  2154. procedure TGLSCustomMemo.WMGetDlgCode(var Msg: TWMGetDlgCode);
  2155. begin
  2156. Msg.Result := DLGC_WANTARROWS or DLGC_WANTTAB;
  2157. end;
  2158. //--------------------------------------------------------------
  2159. // WM_ERASEBKGND
  2160. //--------------------------------------------------------------
  2161. procedure TGLSCustomMemo.WMEraseBkgnd(var Msg: TWmEraseBkgnd);
  2162. begin
  2163. Msg.Result := 1;
  2164. end;
  2165. //--------------------------------------------------------------
  2166. // WM_SIZE
  2167. //--------------------------------------------------------------
  2168. procedure TGLSCustomMemo.WMSize(var Msg: TWMSize);
  2169. begin
  2170. if not (csLoading in ComponentState) then
  2171. try
  2172. ResizeEditor;
  2173. except
  2174. end;
  2175. end;
  2176. //--------------------------------------------------------------
  2177. // WM_SETCURSOR
  2178. //--------------------------------------------------------------
  2179. procedure TGLSCustomMemo.WMSetCursor(var Msg: TWMSetCursor);
  2180. var
  2181. P: TPoint;
  2182. begin
  2183. Msg.Result := 1;
  2184. GetCursorPos(P);
  2185. P := ScreenToClient(P);
  2186. if PointInRect(P, EditorRect) then
  2187. Winapi.Windows.SetCursor(Screen.Cursors[crIBeam])
  2188. else
  2189. Winapi.Windows.SetCursor(Screen.Cursors[crArrow]);
  2190. end;
  2191. //--------------------------------------------------------------
  2192. // WM_SETFOCUS
  2193. //--------------------------------------------------------------
  2194. procedure TGLSCustomMemo.WMSetFocus(var Msg: TWMSetFocus);
  2195. begin
  2196. if FCellSize.H = 0 then
  2197. SetFont(FFont);
  2198. CreateCaret(Handle, HBITMAP(0), 2, FCellSize.H - 2);
  2199. ShowCaret(true);
  2200. end;
  2201. //--------------------------------------------------------------
  2202. // WM_KILLFOCUS
  2203. //--------------------------------------------------------------
  2204. procedure TGLSCustomMemo.WMKillFocus(var Msg: TWMSetFocus);
  2205. begin
  2206. DestroyCaret;
  2207. FCaretVisible := False;
  2208. inherited;
  2209. end;
  2210. //--------------------------------------------------------------
  2211. // SHOW CARET
  2212. //--------------------------------------------------------------
  2213. procedure TGLSCustomMemo.ShowCaret(State: Boolean);
  2214. var
  2215. rct: TRect;
  2216. begin
  2217. FCaretVisible := False;
  2218. if not State then
  2219. HideCaret(Handle)
  2220. else if Focused and not HiddenCaret then
  2221. begin
  2222. rct := CellRect(CurX - FLeftCol, CurY - FTopLine);
  2223. SetCaretPos(rct.Left, rct.Top + 1);
  2224. Winapi.Windows.ShowCaret(Handle);
  2225. FCaretVisible := True;
  2226. end;
  2227. end;
  2228. //--------------------------------------------------------------
  2229. // CELL RECT
  2230. //--------------------------------------------------------------
  2231. function TGLSCustomMemo.CellRect(ACol, ARow: integer): TRect;
  2232. var
  2233. rct: TRect;
  2234. begin
  2235. rct := EditorRect;
  2236. with FCellSize do
  2237. Result := Rect(rct.Left + W * ACol, rct.Top + H * ARow,
  2238. rct.Left + W * (ACol + 1), rct.Top + H * (ARow + 1));
  2239. end;
  2240. //--------------------------------------------------------------
  2241. // LINE RECT
  2242. //--------------------------------------------------------------
  2243. function TGLSCustomMemo.LineRect(ARow: integer): TRect;
  2244. var
  2245. rct: TRect;
  2246. begin
  2247. rct := EditorRect;
  2248. ARow := ARow - FTopLine;
  2249. with FCellSize do
  2250. Result := Rect(rct.Left, rct.Top + H * ARow, rct.Right, rct.Top + H * (ARow
  2251. + 1));
  2252. end;
  2253. //--------------------------------------------------------------
  2254. // COL RECT
  2255. //--------------------------------------------------------------
  2256. function TGLSCustomMemo.ColRect(ACol: integer): TRect;
  2257. var
  2258. rct: TRect;
  2259. begin
  2260. rct := EditorRect;
  2261. ACol := ACol - FLeftCol;
  2262. with FCellSize do
  2263. Result := Rect(rct.Left + W * ACol, rct.Top, rct.Left + W * (ACol + 1),
  2264. rct.Bottom);
  2265. end;
  2266. //--------------------------------------------------------------
  2267. // LINE RANGE RECT
  2268. //--------------------------------------------------------------
  2269. function TGLSCustomMemo.LineRangeRect(FromLine, ToLine: integer): TRect;
  2270. var
  2271. rct1, rct2: TRect;
  2272. begin
  2273. rct1 := LineRect(FromLine);
  2274. rct2 := LineRect(ToLine);
  2275. Result := TotalRect(rct1, rct2);
  2276. end;
  2277. //--------------------------------------------------------------
  2278. // INVALIDATE LINE RANGE
  2279. //--------------------------------------------------------------
  2280. procedure TGLSCustomMemo.InvalidateLineRange(FromLine, ToLine: integer);
  2281. var
  2282. rct: TRect;
  2283. begin
  2284. if ToLine < FromLine then
  2285. ToLine := Lines.Count - 1;
  2286. rct := LineRangeRect(FromLine, ToLine);
  2287. if GutterWidth > 2 then
  2288. rct.Left := FGutter.Left;
  2289. InvalidateRect(Handle, @rct, True);
  2290. end;
  2291. //--------------------------------------------------------------
  2292. // COL RANGE RECT
  2293. //--------------------------------------------------------------
  2294. function TGLSCustomMemo.ColRangeRect(FromCol, ToCol: integer): TRect;
  2295. var
  2296. rct1, rct2: TRect;
  2297. begin
  2298. rct1 := ColRect(FromCol);
  2299. rct2 := ColRect(ToCol);
  2300. Result := TotalRect(rct1, rct2);
  2301. end;
  2302. //--------------------------------------------------------------
  2303. // CELL and CHAR FROM POS
  2304. //--------------------------------------------------------------
  2305. function TGLSCustomMemo.CellFromPos(X, Y: integer): TCellPos;
  2306. var
  2307. rct: TRect;
  2308. begin
  2309. rct := EditorRect;
  2310. if (FCellSize.H = 0) and Assigned(FFont) then
  2311. SetFont(FFont);
  2312. if (FCellSize.W <> 0) and (FCellSize.H <> 0) then
  2313. begin
  2314. Result.X := (X - rct.Left) div FCellSize.W;
  2315. Result.Y := (Y - rct.Top) div FCellSize.H;
  2316. end
  2317. else
  2318. begin
  2319. Result.X := 0;
  2320. Result.Y := 0;
  2321. end;
  2322. end;
  2323. function TGLSCustomMemo.CharFromPos(X, Y: integer): TFullPos;
  2324. var
  2325. rct: TRect;
  2326. begin
  2327. rct := EditorRect;
  2328. if (FCellSize.H = 0) and Assigned(FFont) then
  2329. SetFont(FFont);
  2330. if (FCellSize.W <> 0) and (FCellSize.H <> 0) then
  2331. begin
  2332. Result.Pos := (X - rct.Left) div FCellSize.W + FLeftCol;
  2333. Result.LineNo := (Y - rct.Top) div FCellSize.H + FTopLine;
  2334. end
  2335. else
  2336. begin
  2337. Result.Pos := 1;
  2338. Result.LineNo := 1;
  2339. end;
  2340. end;
  2341. //--------------------------------------------------------------
  2342. // SET COLOR
  2343. //--------------------------------------------------------------
  2344. procedure TGLSCustomMemo.SetColor(Index: integer; Value: TColor);
  2345. var
  2346. eRect: TRect;
  2347. Changed: Boolean;
  2348. begin
  2349. Changed := False;
  2350. case Index of
  2351. 0: if FBkColor <> Value then
  2352. begin
  2353. FBkColor := Value;
  2354. FStyles.BkColor[0] := Value;
  2355. Changed := True;
  2356. end;
  2357. 1: if FSelColor <> Value then
  2358. begin
  2359. FSelColor := Value;
  2360. Changed := True;
  2361. end;
  2362. 2: if FSelBkColor <> Value then
  2363. begin
  2364. FSelBkColor := Value;
  2365. Changed := True;
  2366. end;
  2367. end;
  2368. if Changed then
  2369. begin
  2370. eRect := EditorRect;
  2371. InvalidateRect(Handle, @eRect, True);
  2372. end;
  2373. end;
  2374. //--------------------------------------------------------------
  2375. // SET FONT
  2376. //--------------------------------------------------------------
  2377. procedure TGLSCustomMemo.SetFont(Value: TFont);
  2378. var
  2379. wW, wi: integer;
  2380. OldFontName: string;
  2381. eRect: TRect;
  2382. begin
  2383. OldFontName := Canvas.Font.Name;
  2384. Canvas.Font.Name := Value.Name;
  2385. wW := Canvas.TextWidth('W');
  2386. wi := Canvas.TextWidth('i');
  2387. Canvas.Font.Name := OldFontName;
  2388. if wW <> wi then
  2389. raise EAbort.Create('Monospace font required');
  2390. FFont.Assign(Value);
  2391. Canvas.Font.Assign(Value);
  2392. FCellSize.W := Canvas.TextWidth('W');
  2393. FCellSize.H := Canvas.TextHeight('W') + 1;
  2394. if FCaretVisible then
  2395. begin
  2396. ShowCaret(False);
  2397. DestroyCaret;
  2398. CreateCaret(Handle, HBITMAP(0), 2, FCellSize.H - 2);
  2399. ShowCaret(true);
  2400. end;
  2401. FStyles.TextColor[0] := FFont.Color;
  2402. FStyles.Style[0] := FFont.Style;
  2403. eRect := EditorRect;
  2404. InvalidateRect(Handle, @eRect, True);
  2405. end;
  2406. //--------------------------------------------------------------
  2407. // SET GUTTER WIDTH
  2408. //--------------------------------------------------------------
  2409. procedure TGLSCustomMemo.SetGutterWidth(Value: integer);
  2410. begin
  2411. FGutterWidth := Value;
  2412. FGutter.FWidth := Value;
  2413. if not (csLoading in ComponentState) then
  2414. ResizeEditor;
  2415. end;
  2416. //--------------------------------------------------------------
  2417. // SET GUTTER COLOR
  2418. //--------------------------------------------------------------
  2419. procedure TGLSCustomMemo.SetGutterColor(Value: TColor);
  2420. begin
  2421. if FGutter.FColor <> Value then
  2422. begin
  2423. FGutter.FColor := Value;
  2424. FGutter.Invalidate;
  2425. end;
  2426. end;
  2427. //--------------------------------------------------------------
  2428. // GET GUTTER COLOR
  2429. //--------------------------------------------------------------
  2430. function TGLSCustomMemo.GetGutterColor: TColor;
  2431. begin
  2432. Result := FGutter.FColor;
  2433. end;
  2434. //--------------------------------------------------------------
  2435. // CHAR STYLE NO
  2436. //--------------------------------------------------------------
  2437. function TGLSCustomMemo.CharStyleNo(LineNo, Pos: integer): integer;
  2438. var
  2439. ChStyle: string;
  2440. begin
  2441. Result := 0;
  2442. if (LineNo < 0) or (LineNo >= Lines.Count) then
  2443. Exit;
  2444. ChStyle := CharAttrs[LineNo];
  2445. if (Pos <= 0) or (Pos > Length(ChStyle)) then
  2446. Exit;
  2447. Result := integer(ChStyle[Pos]);
  2448. end;
  2449. //--------------------------------------------------------------
  2450. // DRAW LINE
  2451. //--------------------------------------------------------------
  2452. procedure TGLSCustomMemo.DrawLine(LineNo: integer);
  2453. var
  2454. eRect, rct0, rct1, rct, lineRct: TRect;
  2455. LineSelStart, LineSelEnd, LineStyleNo, pos: integer;
  2456. S, S1, S2, S3, ChStyle: string;
  2457. //--------- FIND LINE SELECTION -------------
  2458. procedure FindLineSelection;
  2459. var
  2460. len: integer;
  2461. xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
  2462. begin
  2463. xSelStartX := FSelStartX;
  2464. xSelStartY := FSelStartY;
  2465. xSelEndX := FSelEndX;
  2466. xSelEndY := FSelEndY;
  2467. OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
  2468. len := Length(Lines[LineNo]);
  2469. LineSelStart := 0;
  2470. LineSelEnd := 0;
  2471. if xSelStartY = Lineno then
  2472. begin
  2473. LineSelStart := xSelStartX - FLeftCol;
  2474. LineSelEnd := len - FLeftCol;
  2475. end
  2476. else if (xSelStartY < LineNo) and (LineNo < xSelEndY) then
  2477. begin
  2478. LineSelStart := 0;
  2479. LineSelEnd := len - FLeftCol;
  2480. end;
  2481. if xSelEndY = LineNo then
  2482. LineSelEnd := xSelEndX - FLeftCol;
  2483. if LineSelEnd < LineSelStart then
  2484. Swap(LineSelEnd, LineSelStart);
  2485. if LineSelStart < 0 then
  2486. LineSelStart := 0;
  2487. S := Copy(Lines[LineNo], FLeftCol + 1, len);
  2488. S1 := Copy(S, 1, LineSelStart);
  2489. S2 := Copy(S, LineSelStart + 1, LineSelEnd - LineSelStart);
  2490. S3 := Copy(S, LineSelEnd + 1, len);
  2491. end;
  2492. //------------- DRAW PART ---------------------
  2493. procedure DrawPart(const Part: string; PartStyle, StartPos: integer;
  2494. var rct: TRect; IsSelection: Boolean);
  2495. var
  2496. len, w: integer;
  2497. rctInternal: TRect;
  2498. begin
  2499. len := Length(Part);
  2500. if len > 0 then
  2501. with FLineBitmap.Canvas do
  2502. begin
  2503. w := FCellSize.W * len;
  2504. Font.Style := FStyles.Style[PartStyle];
  2505. if IsSelection then
  2506. begin
  2507. Font.Color := SelColor;
  2508. Brush.Color := SelBkColor;
  2509. end
  2510. else
  2511. begin
  2512. if LineStyleNo = 0 then
  2513. begin
  2514. Font.Color := FStyles.TextColor[PartStyle];
  2515. Brush.Color := FStyles.BkColor[PartStyle];
  2516. end
  2517. else
  2518. begin
  2519. if (LineNo = FSelCharPos.LineNo) and
  2520. (StartPos = FSelCharPos.Pos + 1) and (Length(Part) = 1) then
  2521. begin
  2522. Font.Color := FStyles.TextColor[PartStyle];
  2523. Brush.Color := FStyles.BkColor[PartStyle];
  2524. end
  2525. else
  2526. begin
  2527. Font.Color := FStyles.TextColor[LineStyleNo];
  2528. Brush.Color := FStyles.BkColor[LineStyleNo];
  2529. Font.Style := FStyles.Style[LineStyleNo];
  2530. end;
  2531. end;
  2532. end;
  2533. rct.Right := rct.Left + w;
  2534. rctInternal := rct;
  2535. rctInternal.Left := rctInternal.Left - eRect.Left;
  2536. rctInternal.Right := rctInternal.Right - eRect.Left;
  2537. rctInternal.Top := rctInternal.Top - rct.Top;
  2538. rctInternal.Bottom := rctInternal.Bottom - rct.Top;
  2539. FillRect(rctInternal);
  2540. DrawText(Handle, PChar(Part), len, rctInternal, DT_LEFT
  2541. or DT_SINGLELINE or DT_NOPREFIX);
  2542. rct0.Left := rct.Left + w;
  2543. rct := rct0;
  2544. end;
  2545. end;
  2546. //------------- DRAW SEGMENTS ---------------------
  2547. procedure DrawSegments(S: string; WorkPos: integer;
  2548. var rct: TRect; IsSelection: Boolean);
  2549. var
  2550. i, len, ThisStyle: integer;
  2551. begin
  2552. while True do
  2553. begin
  2554. Len := Length(S);
  2555. if Len = 0 then
  2556. Exit;
  2557. ThisStyle := Ord(ChStyle[WorkPos]);
  2558. i := 1;
  2559. while (i <= Len) and
  2560. (ThisStyle = Ord(ChStyle[WorkPos + i - 1])) do
  2561. Inc(i);
  2562. DrawPart(Copy(S, 1, i - 1), ThisStyle, WorkPos, rct, IsSelection);
  2563. Inc(WorkPos, i - 1);
  2564. s := Copy(s, i, Len);
  2565. end;
  2566. end;
  2567. //---------------------------------------------
  2568. begin
  2569. eRect := EditorRect;
  2570. rct := CellRect(0, LineNo - FTopLine);
  2571. rct0 := Rect(eRect.Left, rct.Top, eRect.Right, rct.Bottom);
  2572. lineRct := rct0;
  2573. if LineNo < Lines.Count then
  2574. begin
  2575. rct := rct0;
  2576. S := Lines[LineNo];
  2577. LineStyleNo := LineStyle[LineNo];
  2578. ChStyle := CharAttrs[LineNo];
  2579. FindLineSelection;
  2580. if not Assigned(FOnGetLineAttrs) then
  2581. ChStyle := StringOfChar(#0, Length(Lines[LineNo]));
  2582. if Length(S) > 0 then
  2583. if (FSelCharStyle >= 0) and (LineNo = FSelCharPos.LineNo) then
  2584. ChStyle[FSelCharPos.Pos + 1] := Char(FSelCharStyle);
  2585. pos := FLeftCol + 1; // 1
  2586. DrawSegments(S1, pos, rct, False);
  2587. Inc(pos, Length(S1));
  2588. DrawSegments(S2, pos, rct, True);
  2589. Inc(pos, Length(S2));
  2590. DrawSegments(S3, pos, rct, False);
  2591. // else begin
  2592. // DrawPart(S1,StyleNo,rct,False);
  2593. // DrawPart(S2,StyleNo,rct,True);
  2594. // DrawPart(S3,StyleNo,rct,False);
  2595. // end;
  2596. rct1 := rct;
  2597. rct1.Left := rct1.Left - eRect.Left;
  2598. rct1.Right := rct1.Right - eRect.Left;
  2599. rct1.Top := rct1.Top - rct.Top;
  2600. rct1.Bottom := rct1.Bottom - rct.Top;
  2601. with FLineBitmap.Canvas do
  2602. begin
  2603. Brush.Color := FStyles.BkColor[LineStyleNo];
  2604. FillRect(rct1);
  2605. end;
  2606. with LineRct do
  2607. BitBlt(Canvas.Handle, Left, Top, Right - Left, Bottom - Top,
  2608. FLineBitmap.Canvas.Handle, 0, 0, SRCCOPY);
  2609. end
  2610. else
  2611. with Canvas do
  2612. begin
  2613. Brush.Color := BkColor;
  2614. FillRect(rct0);
  2615. end;
  2616. end;
  2617. //--------------------------------------------------------------
  2618. // SET HIDDEN CARET
  2619. //--------------------------------------------------------------
  2620. procedure TGLSCustomMemo.SetHiddenCaret(Value: Boolean);
  2621. begin
  2622. if Value <> FHiddenCaret then
  2623. begin
  2624. FHiddenCaret := Value;
  2625. if Focused then
  2626. if FHiddenCaret = FCaretVisible then
  2627. ShowCaret(not FHiddenCaret);
  2628. end;
  2629. end;
  2630. //--------------------------------------------------------------
  2631. // BORDER
  2632. //--------------------------------------------------------------
  2633. procedure Border(Canvas: TCanvas; const rct: TRect; BorderType: TBorderType);
  2634. const
  2635. Colors: array[TBorderType] of array[1..4] of TColor
  2636. = (($D0D0D0, clWhite, clGray, clBlack),
  2637. (clGray, clBlack, $D0D0D0, clWhite),
  2638. (clWhite, clWhite, clWhite, clGray),
  2639. (clGray, clWhite, clWhite, clGray));
  2640. begin
  2641. with Canvas do
  2642. begin
  2643. Pen.Color := Colors[BorderType][1];
  2644. MoveTo(rct.Left, rct.Bottom - 1);
  2645. LineTo(rct.Left, rct.Top);
  2646. LineTo(rct.Right, rct.Top);
  2647. if BorderType in [btRaised, btLowered] then
  2648. begin
  2649. Pen.Color := Colors[BorderType][2];
  2650. MoveTo(rct.Left + 1, rct.Bottom);
  2651. LineTo(rct.Left + 1, rct.Top + 1);
  2652. LineTo(rct.Right, rct.Top + 1);
  2653. Pen.Color := Colors[BorderType][3];
  2654. MoveTo(rct.Left + 1, rct.Bottom - 2);
  2655. LineTo(rct.Right - 2, rct.Bottom - 2);
  2656. LineTo(rct.Right - 2, rct.Top + 1);
  2657. end;
  2658. Pen.Color := Colors[BorderType][4];
  2659. MoveTo(rct.Left, rct.Bottom - 1);
  2660. LineTo(rct.Right - 1, rct.Bottom - 1);
  2661. LineTo(rct.Right - 1, rct.Top);
  2662. end;
  2663. end;
  2664. //--------------------------------------------------------------
  2665. // EDITOR RECT
  2666. //--------------------------------------------------------------
  2667. function TGLSCustomMemo.EditorRect: TRect;
  2668. var
  2669. l, t, r, b: integer;
  2670. begin
  2671. l := 2;
  2672. r := Width - 2;
  2673. t := 2;
  2674. b := Height - 2;
  2675. if GutterWidth > 2 then
  2676. l := l + GutterWidth;
  2677. if FScrollBars in [ssBoth, ssVertical] then
  2678. r := r - FScrollBarWidth;
  2679. if FScrollBars in [ssBoth, ssHorizontal] then
  2680. b := b - FScrollBarWidth;
  2681. Result := Rect(l + FMargin, t, r, b);
  2682. end;
  2683. //--------------------------------------------------------------
  2684. // DRAW MARGIN
  2685. //--------------------------------------------------------------
  2686. procedure TGLSCustomMemo.DrawMargin;
  2687. var
  2688. eRect: TRect;
  2689. i: integer;
  2690. begin
  2691. eRect := EditorRect;
  2692. with Canvas do
  2693. begin
  2694. Pen.Color := clWhite;
  2695. for i := 1 to FMargin do
  2696. begin
  2697. MoveTo(eRect.Left - i, eRect.Top);
  2698. LineTo(eRect.Left - i, eRect.Bottom + 1);
  2699. end;
  2700. end;
  2701. end;
  2702. //--------------------------------------------------------------
  2703. // DRAW GUTTER
  2704. //--------------------------------------------------------------
  2705. procedure TGLSCustomMemo.DrawGutter;
  2706. begin
  2707. if GutterWidth < 2 then
  2708. Exit;
  2709. ResizeGutter;
  2710. FGutter.PaintTo(Canvas);
  2711. end;
  2712. //--------------------------------------------------------------
  2713. // DRAW SCROLLBARS
  2714. //--------------------------------------------------------------
  2715. procedure TGLSCustomMemo.DrawScrollBars;
  2716. begin
  2717. ResizeScrollBars;
  2718. if FScrollBars in [ssBoth, ssVertical] then
  2719. sbVert.PaintTo(Canvas);
  2720. if FScrollBars in [ssBoth, ssHorizontal] then
  2721. sbHorz.PaintTo(Canvas);
  2722. if FScrollBars = ssBoth then
  2723. with Canvas do
  2724. begin
  2725. Brush.Color := clSilver;
  2726. FillRect(Rect(sbVert.Left, sbHorz.Top + 1,
  2727. sbVert.Left + sbVert.Width, sbHorz.Top + sbHorz.Height));
  2728. end;
  2729. end;
  2730. //--------------------------------------------------------------
  2731. // FRESH LINE BITMAP
  2732. //--------------------------------------------------------------
  2733. procedure TGLSCustomMemo.FreshLineBitmap;
  2734. var
  2735. eRect: TRect;
  2736. begin
  2737. eRect := EditorRect;
  2738. with FLineBitmap do
  2739. begin
  2740. Width := eRect.Right - eRect.Left;
  2741. Height := FCellSize.H;
  2742. FLineBitmap.Canvas.Font.Assign(Self.Canvas.Font);
  2743. end;
  2744. end;
  2745. //--------------------------------------------------------------
  2746. // PAINT
  2747. //--------------------------------------------------------------
  2748. procedure TGLSCustomMemo.Paint;
  2749. var
  2750. pTop, pBottom: TFullPos;
  2751. rct, eRect: TRect;
  2752. i: integer;
  2753. clipRgn: HRGN;
  2754. Attrs: string;
  2755. begin
  2756. if TGLSMemoStrings(Lines).FLockCount > 0 then
  2757. Exit;
  2758. with Canvas do
  2759. begin
  2760. if FCellSize.H = 0 then
  2761. SetFont(FFont);
  2762. FreshLineBitmap;
  2763. Border(Canvas, Rect(0, 0, Width, Height), btLowered);
  2764. DrawMargin;
  2765. DrawGutter;
  2766. DrawScrollBars;
  2767. eRect := EditorRect;
  2768. clipRgn := CreateRectRgn(eRect.Left, eRect.Top, eRect.Right, eRect.Bottom);
  2769. ExtSelectClipRgn(Canvas.Handle, clipRgn, RGN_AND);
  2770. DeleteObject(clipRgn);
  2771. rct := Canvas.ClipRect;
  2772. pTop := CharFromPos(rct.Left, rct.Top);
  2773. pBottom := CharFromPos(rct.Left, rct.Bottom);
  2774. if Assigned(FOnGetLineAttrs) then
  2775. for i := 0 to Lines.Count - 1 do
  2776. if not ValidAttrs[i] then
  2777. begin
  2778. FOnGetLineAttrs(Self, i, Attrs);
  2779. CharAttrs[i] := Attrs;
  2780. ValidAttrs[i] := True;
  2781. end;
  2782. for i := pTop.LineNo to pBottom.LineNo do
  2783. DrawLine(i);
  2784. end;
  2785. end;
  2786. //--------------------------------------------------------------
  2787. // GET VISIBLE
  2788. //--------------------------------------------------------------
  2789. function TGLSCustomMemo.GetVisible(Index: integer): integer;
  2790. var
  2791. Coord: TFullPos;
  2792. Cell: TCellPos;
  2793. eRect: TRect;
  2794. begin
  2795. eRect := EditorRect;
  2796. Coord := CharFromPos(eRect.Right - 1, eRect.Bottom - 1);
  2797. Cell := CellFromPos(eRect.Right - 1, eRect.Bottom - 1);
  2798. case Index of
  2799. 0: Result := Cell.X;
  2800. 1: Result := Cell.Y;
  2801. 2: Result := Coord.Pos - 1;
  2802. 3: Result := Coord.LineNo - 1;
  2803. else
  2804. Result := 0;
  2805. end;
  2806. end;
  2807. //--------------------------------------------------------------
  2808. // IS LINE VISIBLE
  2809. //--------------------------------------------------------------
  2810. function TGLSCustomMemo.IsLineVisible(LineNo: integer): Boolean;
  2811. begin
  2812. if FCellSize.H = 0 then
  2813. SetFont(FFont);
  2814. Result := (FTopLine <= LineNo) and (LineNo <= LastVisibleLine + 1);
  2815. end;
  2816. //--------------------------------------------------------------
  2817. // MAKE VISIBLE
  2818. //--------------------------------------------------------------
  2819. procedure TGLSCustomMemo.MakeVisible;
  2820. var
  2821. Modified: Boolean;
  2822. begin
  2823. Modified := False;
  2824. if CurX < FLeftCol then
  2825. begin
  2826. FLeftCol := CurX - 2;
  2827. if FLeftCol < 0 then
  2828. FLeftCol := 0;
  2829. Modified := True;
  2830. end;
  2831. if CurX > LastVisiblePos then
  2832. begin
  2833. if (FScrollBars in [ssBoth, ssHorizontal]) or
  2834. (ScrollMode = smAuto) then
  2835. begin
  2836. FLeftCol := FLeftCol + CurX - LastVisiblePos + 2;
  2837. end
  2838. else
  2839. CurX := LastVisiblePos;
  2840. Modified := True;
  2841. end;
  2842. if CurY < FTopLine then
  2843. begin
  2844. FTopLine := CurY;
  2845. if FTopLine < 0 then
  2846. FTopLine := 0;
  2847. Modified := True;
  2848. end;
  2849. if CurY > LastVisibleLine then
  2850. begin
  2851. if (FScrollBars in [ssBoth, ssVertical]) or
  2852. (ScrollMode = smAuto) then
  2853. begin
  2854. FTopLine := FTopLine + CurY - LastVisibleLine;
  2855. end
  2856. else
  2857. CurY := LastVisibleLine;
  2858. Modified := True;
  2859. end;
  2860. if Modified then
  2861. Invalidate;
  2862. end;
  2863. //--------------------------------------------------------------
  2864. // RESIZE EDITOR
  2865. //--------------------------------------------------------------
  2866. procedure TGLSCustomMemo.ResizeEditor;
  2867. begin
  2868. ResizeScrollBars;
  2869. ResizeGutter;
  2870. MakeVisible;
  2871. Invalidate;
  2872. end;
  2873. //--------------------------------------------------------------
  2874. // FIND TEXT
  2875. //--------------------------------------------------------------
  2876. function TGLSCustomMemo.FindText(Text: string; Options: TFindOptions; Select:
  2877. Boolean): Boolean;
  2878. var
  2879. i, p: integer;
  2880. s1, s0, s: string;
  2881. //-----------------------------------------------------------
  2882. function LastPos(const Substr, s: string): integer;
  2883. var
  2884. i, j, lenSub: integer;
  2885. begin
  2886. Result := 0;
  2887. lenSub := Length(Substr);
  2888. i := Length(s) - lenSub + 1;
  2889. while i > 0 do
  2890. begin
  2891. if s[i] = Substr[1] then
  2892. begin
  2893. Result := i;
  2894. for j := i + 1 to i + lenSub - 1 do
  2895. if s[j] <> Substr[j - i + 1] then
  2896. begin
  2897. Result := 0;
  2898. break;
  2899. end;
  2900. end;
  2901. if Result <> 0 then
  2902. break;
  2903. Dec(i);
  2904. end;
  2905. end;
  2906. //-----------------------------------------------------------
  2907. begin
  2908. Result := False;
  2909. if not (frMatchCase in Options) then
  2910. Text := AnsiLowerCase(Text);
  2911. if SelLength > 0 then
  2912. ClearSelection;
  2913. s := Lines[CurY];
  2914. s0 := Copy(s, 1, CurX);
  2915. s1 := Copy(s, CurX + 1, Length(s));
  2916. i := CurY;
  2917. while True do
  2918. begin
  2919. if not (frMatchCase in Options) then
  2920. begin
  2921. s0 := AnsiLowerCase(s0);
  2922. s1 := AnsiLowerCase(s1);
  2923. end;
  2924. if frDown in Options then
  2925. p := Pos(Text, s1)
  2926. else
  2927. p := LastPos(Text, s0);
  2928. if p > 0 then
  2929. begin
  2930. Result := True;
  2931. CurY := i;
  2932. if frDown in Options then
  2933. CurX := Length(s0) + p - 1
  2934. else
  2935. CurX := p - 1;
  2936. if Select then
  2937. begin
  2938. if not (frDown in Options) then
  2939. CurX := CurX + Length(Text);
  2940. ClearSelection;
  2941. if frDown in Options then
  2942. CurX := CurX + Length(Text)
  2943. else
  2944. CurX := CurX - Length(Text);
  2945. ExpandSelection;
  2946. end;
  2947. break;
  2948. end;
  2949. if frDown in Options then
  2950. Inc(i)
  2951. else
  2952. Dec(i);
  2953. if (i < 0) or (i > Lines.Count - 1) then
  2954. break;
  2955. if frDown in Options then
  2956. begin
  2957. s0 := '';
  2958. s1 := Lines[i];
  2959. end
  2960. else
  2961. begin
  2962. s0 := Lines[i];
  2963. s1 := '';
  2964. end;
  2965. end;
  2966. end;
  2967. //--------------------------------------------------------------
  2968. // RESIZE SCROLLBARS
  2969. //--------------------------------------------------------------
  2970. procedure TGLSCustomMemo.ResizeScrollBars;
  2971. var
  2972. eRect, sbRect: TRect;
  2973. MaxLen, OldMax, NewTop, Margin: integer;
  2974. begin
  2975. eRect := EditorRect;
  2976. if FScrollBars in [ssBoth, ssVertical] then
  2977. begin
  2978. with sbVert do
  2979. begin
  2980. Width := 16;
  2981. Height := eRect.Bottom - eRect.Top + 1;
  2982. Left := eRect.Right;
  2983. Top := eRect.Top;
  2984. OldMax := MaxPosition;
  2985. MaxPosition := (Lines.Count - 1) - (LastVisibleLine - FTopLine);
  2986. NewTop := FTopLine;
  2987. if (FTopLine > 0) and (LastVisibleLine > Lines.Count - 1) then
  2988. begin
  2989. Dec(NewTop, LastVisibleLine - (Lines.Count - 1));
  2990. if NewTop < 0 then
  2991. NewTop := 0;
  2992. MaxPosition := NewTop;
  2993. end;
  2994. if MaxPosition < 0 then
  2995. MaxPosition := 0;
  2996. Position := NewTop;
  2997. Total := Lines.Count;
  2998. if OldMax <> MaxPosition then
  2999. begin
  3000. if NewTop <> FTopLine then
  3001. begin
  3002. DoScroll(sbVert, NewTop - FTopLine);
  3003. FGutter.Invalidate;
  3004. end;
  3005. sbRect := sbVert.FullRect;
  3006. InvalidateRect(Handle, @sbRect, True);
  3007. end;
  3008. end;
  3009. end;
  3010. if FScrollBars in [ssBoth, ssHorizontal] then
  3011. begin
  3012. MaxLen := MaxLength;
  3013. with sbHorz do
  3014. begin
  3015. Width := Self.Width - 4;
  3016. if FScrollBars = ssBoth then
  3017. Width := Width - sbVert.Width;
  3018. Height := 16;
  3019. Left := 2;
  3020. Top := eRect.Bottom;
  3021. OldMax := MaxPosition;
  3022. Margin := LastVisiblePos - MaxLen;
  3023. if Margin < 2 then
  3024. Margin := 2;
  3025. MaxPosition := MaxLen - (LastVisiblePos - FLeftCol) + Margin;
  3026. if MaxPosition < 0 then
  3027. MaxPosition := 0;
  3028. Position := FLeftCol;
  3029. Total := MaxLen;
  3030. if OldMax <> MaxPosition then
  3031. begin
  3032. if MaxPosition = 0 then
  3033. begin
  3034. FLeftCol := 0;
  3035. InvalidateRect(Handle, @eRect, True);
  3036. ;
  3037. FGutter.Invalidate;
  3038. end;
  3039. sbRect := sbHorz.FullRect;
  3040. InvalidateRect(Handle, @sbRect, True);
  3041. end;
  3042. end;
  3043. end;
  3044. end;
  3045. //--------------------------------------------------------------
  3046. // RESIZE GUTTER
  3047. //--------------------------------------------------------------
  3048. procedure TGLSCustomMemo.ResizeGutter;
  3049. var
  3050. eRect: TRect;
  3051. begin
  3052. eRect := EditorRect;
  3053. with FGutter do
  3054. begin
  3055. Height := eRect.Bottom - eRect.Top;
  3056. end;
  3057. end;
  3058. //--------------------------------------------------------------
  3059. // CREATE PARAMS
  3060. //--------------------------------------------------------------
  3061. procedure TGLSCustomMemo.CreateParams(var Params: TCreateParams);
  3062. begin
  3063. inherited;
  3064. end;
  3065. //--------------------------------------------------------------
  3066. // UNDO, REDO
  3067. //--------------------------------------------------------------
  3068. procedure TGLSCustomMemo.Undo;
  3069. begin
  3070. FUndoList.Undo;
  3071. end;
  3072. procedure TGLSCustomMemo.Redo;
  3073. begin
  3074. FUndoList.Redo;
  3075. end;
  3076. //--------------------------------------------------------------
  3077. // SET UNDO LIMIT
  3078. //--------------------------------------------------------------
  3079. procedure TGLSCustomMemo.SetUndoLimit(Value: integer);
  3080. begin
  3081. if (FUndoLimit <> Value) then
  3082. begin
  3083. if Value <= 0 then
  3084. Value := 1;
  3085. if Value > 100 then
  3086. Value := 100;
  3087. FUndoLimit := Value;
  3088. FUndoList.Limit := Value;
  3089. end;
  3090. end;
  3091. //--------------------------------------------------------------
  3092. // UNDO (REDO) CHANGE
  3093. //--------------------------------------------------------------
  3094. procedure TGLSCustomMemo.UndoChange;
  3095. begin
  3096. if Assigned(FOnUndoChange) then
  3097. FOnUndoChange(Self, FUndoList.Pos < FUndoList.Count,
  3098. FUndoList.Pos > 0);
  3099. end;
  3100. //--------------------------------------------------------------
  3101. // CAN UNDO
  3102. //--------------------------------------------------------------
  3103. function TGLSCustomMemo.CanUndo: boolean;
  3104. begin
  3105. Result := FUndoList.FPos < FUndoList.Count;
  3106. end;
  3107. //--------------------------------------------------------------
  3108. // CAN REDO
  3109. //--------------------------------------------------------------
  3110. function TGLSCustomMemo.CanRedo: Boolean;
  3111. begin
  3112. Result := FUndoList.FPos > 0;
  3113. end;
  3114. //--------------------------------------------------------------
  3115. // CLEAR UNDO LIST
  3116. //--------------------------------------------------------------
  3117. procedure TGLSCustomMemo.ClearUndoList;
  3118. begin
  3119. if Assigned(FUndoList) then
  3120. FUndoList.Clear;
  3121. end;
  3122. //--------------------------------------------------------------
  3123. // SET SCROLL BARS
  3124. //--------------------------------------------------------------
  3125. procedure TGLSCustomMemo.SetScrollBars(Value: System.UITypes.TScrollStyle);
  3126. begin
  3127. if FScrollBars <> Value then
  3128. begin
  3129. FScrollBars := Value;
  3130. if not (csLoading in ComponentState) then
  3131. ResizeEditor;
  3132. end;
  3133. end;
  3134. //--------------------------------------------------------------
  3135. // CREATE
  3136. //--------------------------------------------------------------
  3137. constructor TGLSCustomMemo.Create(AOwner: TComponent);
  3138. begin
  3139. inherited;
  3140. ControlStyle := [csCaptureMouse, csClickEvents,
  3141. csDoubleClicks, csReplicatable];
  3142. Width := 100;
  3143. Height := 40;
  3144. TabStop := True;
  3145. Cursor := crIBeam;
  3146. FFont := TFont.Create;
  3147. FFont.Name := 'Courier New';
  3148. FFont.Size := 10;
  3149. Canvas.Font.Assign(FFont);
  3150. FHiddenCaret := False;
  3151. FCaretVisible := False;
  3152. FCurX := 0;
  3153. FCurY := 0;
  3154. FLeftCol := 0;
  3155. FTopLine := 0;
  3156. FTabSize := 4;
  3157. FMargin := 2;
  3158. FAutoIndent := True;
  3159. FLines := TGLSMemoStrings.Create;
  3160. TGLSMemoStrings(FLines).FMemo := Self;
  3161. FScrollBars := ssBoth;
  3162. FScrollBarWidth := 16;
  3163. sbVert := TGLSMemoScrollBar.Create(Self, sbVertical);
  3164. sbVert.Width := FScrollBarWidth;
  3165. sbHorz := TGLSMemoScrollBar.Create(Self, sbHorizontal);
  3166. sbHorz.Height := FScrollBarWidth;
  3167. FGutter := TGLSMemoGutter.Create;
  3168. with FGutter do
  3169. begin
  3170. FLeft := 2;
  3171. FTop := 2;
  3172. FWidth := 0;
  3173. FHeight := 0;
  3174. FColor := clBtnFace;
  3175. FMemo := Self;
  3176. end;
  3177. FSelStartX := 0;
  3178. FSelStartY := 0;
  3179. FSelEndX := 0;
  3180. FSelEndY := 0;
  3181. FBkColor := clWhite;
  3182. FSelColor := clWhite;
  3183. FSelBkColor := clNavy;
  3184. FStyles := TStyleList.Create;
  3185. FStyles.Add(clBlack, clWhite, []);
  3186. FSelCharPos.LineNo := -1;
  3187. FSelCharPos.Pos := -1;
  3188. FSelCharStyle := -1;
  3189. FLineBitmap := TBitmap.Create;
  3190. FLeftButtonDown := False;
  3191. FScrollMode := smAuto;
  3192. FUndoList := TGLSMemoUndoList.Create;
  3193. FFirstUndoList := FUndoList;
  3194. FUndoList.Memo := Self;
  3195. FUndoLimit := 100;
  3196. TGLSMemoStrings(FLines).DoAdd('');
  3197. FAfterDoubleClick := False;
  3198. end;
  3199. //--------------------------------------------------------------
  3200. // DESTROY
  3201. //--------------------------------------------------------------
  3202. destructor TGLSCustomMemo.Destroy;
  3203. begin
  3204. FFont.Free;
  3205. FLines.Free;
  3206. FGutter.Free;
  3207. sbVert.Free;
  3208. sbHorz.Free;
  3209. FStyles.Free;
  3210. FLineBitmap.Free;
  3211. FFirstUndoList.Free;
  3212. inherited;
  3213. end;
  3214. // ---------------------TGLSMemoScrollBar functions
  3215. procedure TGLSMemoScrollBar.SetParams(Index: integer; Value: integer);
  3216. begin
  3217. case Index of
  3218. 0: if Left <> Value then
  3219. FLeft := Value;
  3220. 1: if Top <> Value then
  3221. FTop := Value;
  3222. 2: if Width <> Value then
  3223. FWidth := Value;
  3224. 3: if Height <> Value then
  3225. FHeight := Value;
  3226. 4: if Total <> Value then
  3227. FTotal := Value;
  3228. 5: if MaxPosition <> Value then
  3229. FMaxPosition := Value;
  3230. 6: if Position <> Value then
  3231. FPosition := Value;
  3232. end;
  3233. end;
  3234. //-------------------- CREATE ------------------------------
  3235. constructor TGLSMemoScrollBar.Create(AParent: TGLSMemoAbstractScrollableObject;
  3236. AKind: TScrollBarKind);
  3237. begin
  3238. FParent := AParent;
  3239. FButtonLength := 16;
  3240. FKind := AKind;
  3241. FState := sbsWait;
  3242. end;
  3243. //-------------------- RECT -----------------------
  3244. function TGLSMemoScrollBar.GetRect: TRect;
  3245. begin
  3246. Result := Rect(Left, Top, Left + Width, Top + Height);
  3247. end;
  3248. //-------------------- GET THUMB RECT -----------------------
  3249. function TGLSMemoScrollBar.GetThumbRect: TRect;
  3250. var
  3251. TotalLen, FreeLen, ThumbLen, ThumbOffset, ThumbCoord: integer;
  3252. K: double;
  3253. begin
  3254. if MaxPosition <= 0 then
  3255. begin
  3256. Result := Rect(0, 0, 0, 0);
  3257. Exit;
  3258. end;
  3259. if Kind = sbVertical then
  3260. TotalLen := Height
  3261. else
  3262. TotalLen := Width;
  3263. FreeLen := TotalLen - 2 * FButtonLength;
  3264. K := (Total - MaxPosition) / MaxPosition;
  3265. if K > 0 then
  3266. begin
  3267. ThumbLen := round(FreeLen * K / (1 + K));
  3268. if ThumbLen < 8 then
  3269. ThumbLen := 8;
  3270. end
  3271. else
  3272. ThumbLen := 8;
  3273. if ThumbLen >= FreeLen then
  3274. Result := Rect(0, 0, 0, 0)
  3275. else
  3276. begin
  3277. ThumbOffset := round((FreeLen - ThumbLen) * Position / MaxPosition);
  3278. ThumbCoord := FButtonLength + ThumbOffset;
  3279. if Kind = sbVertical then
  3280. Result := Rect(Left + 1, Top + ThumbCoord, Left + Width, Top + ThumbCoord
  3281. + ThumbLen)
  3282. else
  3283. Result := Rect(Left + ThumbCoord, Top + 1, Left + ThumbCoord + ThumbLen,
  3284. Top + Height);
  3285. end;
  3286. end;
  3287. //-------------------- GET Back RECT -----------------------
  3288. function TGLSMemoScrollBar.GetBackRect: TRect;
  3289. begin
  3290. if Kind = sbVertical then
  3291. Result := Rect(Left + 1, Top, Left + Width, Top + FButtonLength)
  3292. else
  3293. Result := Rect(Left, Top + 1, Left + FButtonLength, Top + Height);
  3294. end;
  3295. //-------------------- GET MIDDLE RECT -----------------------
  3296. function TGLSMemoScrollBar.GetMiddleRect: TRect;
  3297. var
  3298. bRect, fRect: TRect;
  3299. begin
  3300. bRect := BackRect;
  3301. fRect := ForwardRect;
  3302. if Kind = sbVertical then
  3303. Result := Rect(Left + 1, bRect.Bottom, Left + Width, fRect.Top)
  3304. else
  3305. Result := Rect(bRect.Right, Top + 1, fRect.Left, Top + Height);
  3306. end;
  3307. //-------------------- GET Forward RECT -----------------------
  3308. function TGLSMemoScrollBar.GetForwardRect: TRect;
  3309. begin
  3310. if Kind = sbVertical then
  3311. Result := Rect(Left + 1, Top + Height - FButtonLength, Left + Width, Top +
  3312. Height)
  3313. else
  3314. Result := Rect(Left + Width - FButtonLength, Top + 1, Left + Width, Top +
  3315. Height);
  3316. end;
  3317. //-------------------- GET PAGE BACK RECT -----------------------
  3318. function TGLSMemoScrollBar.GetPgBackRect: TRect;
  3319. var
  3320. thRect: TRect;
  3321. begin
  3322. thRect := GetThumbRect;
  3323. if thRect.Bottom = 0 then
  3324. begin
  3325. Result := Rect(0, 0, 0, 0);
  3326. Exit;
  3327. end;
  3328. if Kind = sbVertical then
  3329. Result := Rect(Left + 1, Top + FButtonLength, Left + Width, thRect.Top - 1)
  3330. else
  3331. Result := Rect(Left + FButtonLength, Top + 1, thRect.Left - 1, Top +
  3332. Height);
  3333. end;
  3334. //-------------------- GET PG FORWARD RECT -----------------------
  3335. function TGLSMemoScrollBar.GetPgForwardRect: TRect;
  3336. var
  3337. thRect: TRect;
  3338. begin
  3339. thRect := GetThumbRect;
  3340. if thRect.Bottom = 0 then
  3341. begin
  3342. Result := Rect(0, 0, 0, 0);
  3343. Exit;
  3344. end;
  3345. if Kind = sbVertical then
  3346. Result := Rect(Left + 1, thRect.Bottom, Left + Width, Top + Height -
  3347. FButtonLength)
  3348. else
  3349. Result := Rect(thRect.Right, Top + 1, Left + Width - FButtonLength, Top +
  3350. Height);
  3351. end;
  3352. //-------------------- PAINT TO -----------------------
  3353. procedure TGLSMemoScrollBar.PaintTo(ACanvas: TCanvas);
  3354. var
  3355. sRect, mRect, gRect, thRect: TRect;
  3356. iconX, iconY, shift: integer;
  3357. begin
  3358. with ACanvas do
  3359. begin
  3360. if Kind = sbVertical then
  3361. begin
  3362. Pen.Color := clSilver;
  3363. MoveTo(Left, Top);
  3364. LineTo(Left, Top + Height);
  3365. sRect := BackRect;
  3366. Brush.Color := clSilver;
  3367. FillRect(sRect);
  3368. if State = sbsBack then
  3369. begin
  3370. shift := 1;
  3371. Pen.Color := clGray;
  3372. with sRect do
  3373. Rectangle(Left, Top, Right, Bottom);
  3374. end
  3375. else
  3376. begin
  3377. shift := 0;
  3378. Border(ACanvas, sRect, btFlatRaised);
  3379. end;
  3380. iconX := sRect.Left + (Width - 1 - 7) div 2;
  3381. iconY := sRect.Top + (FButtonLength - 8) div 2;
  3382. Draw(iconX + shift, iconY + shift, bmScrollBarUp);
  3383. gRect := ForwardRect;
  3384. Brush.Color := clSilver;
  3385. FillRect(gRect);
  3386. if State = sbsForward then
  3387. begin
  3388. shift := 1;
  3389. Pen.Color := clGray;
  3390. with gRect do
  3391. Rectangle(Left, Top, Right, Bottom);
  3392. end
  3393. else
  3394. begin
  3395. shift := 0;
  3396. Border(ACanvas, gRect, btFlatRaised);
  3397. end;
  3398. iconX := gRect.Left + (Width - 1 - 7) div 2;
  3399. iconY := gRect.Top + (FButtonLength - 8) div 2;
  3400. Draw(iconX + shift, iconY + shift, bmScrollBarDown);
  3401. mRect := Rect(sRect.Left, sRect.Bottom, gRect.Right, gRect.Top);
  3402. end
  3403. else
  3404. begin
  3405. Pen.Color := clSilver;
  3406. MoveTo(Left, Top);
  3407. LineTo(Left + Width, Top);
  3408. sRect := BackRect;
  3409. Brush.Color := clSilver;
  3410. FillRect(sRect);
  3411. if State = sbsBack then
  3412. begin
  3413. shift := 1;
  3414. Pen.Color := clGray;
  3415. with sRect do
  3416. Rectangle(Left, Top, Right, Bottom);
  3417. end
  3418. else
  3419. begin
  3420. shift := 0;
  3421. Border(ACanvas, sRect, btFlatRaised);
  3422. end;
  3423. iconX := sRect.Left + shift + (FButtonLength - 8) div 2;
  3424. iconY := sRect.Top + shift + (Height - 1 - 7) div 2;
  3425. Draw(iconX + shift, iconY + shift, bmScrollBarLeft);
  3426. gRect := ForwardRect;
  3427. Brush.Color := clSilver;
  3428. FillRect(gRect);
  3429. if State = sbsForward then
  3430. begin
  3431. shift := 1;
  3432. Pen.Color := clGray;
  3433. with gRect do
  3434. Rectangle(Left, Top, Right, Bottom);
  3435. end
  3436. else
  3437. begin
  3438. shift := 0;
  3439. Border(ACanvas, gRect, btFlatRaised);
  3440. end;
  3441. iconX := gRect.Left + (FButtonLength - 8) div 2;
  3442. iconY := gRect.Top + (Height - 1 - 7) div 2;
  3443. Draw(iconX + shift, iconY + shift, bmScrollBarRight);
  3444. mRect := Rect(sRect.Right, sRect.Top, gRect.Left, gRect.Bottom);
  3445. end;
  3446. Brush.Bitmap := bmScrollBarFill;
  3447. FillRect(mRect);
  3448. Brush.Bitmap := nil;
  3449. if State = sbsPageBack then
  3450. begin
  3451. Brush.Color := clGray;
  3452. FillRect(PageBackRect);
  3453. end;
  3454. if State = sbsPageForward then
  3455. begin
  3456. Brush.Color := clGray;
  3457. FillRect(PageForwardRect);
  3458. end;
  3459. thRect := ThumbRect;
  3460. Brush.Color := clSilver;
  3461. FillRect(thRect);
  3462. Border(ACanvas, thRect, btFlatRaised);
  3463. end;
  3464. end;
  3465. //-------------------- SET STATE ----------
  3466. procedure TGLSMemoScrollBar.SetState(Value: TsbState);
  3467. begin
  3468. if FState <> Value then
  3469. begin
  3470. FState := Value;
  3471. end;
  3472. end;
  3473. //-------------------- MOUSE DOWN ------------
  3474. function TGLSMemoScrollBar.MouseDown(Button: TMouseButton; Shift: TShiftState;
  3475. X,
  3476. Y: Integer):
  3477. Boolean;
  3478. var
  3479. sRect, gRect, thRect, pbRect, pfRect: TRect;
  3480. begin
  3481. Result := False;
  3482. if (Width = 0) or (Height = 0) then
  3483. Exit;
  3484. sRect := BackRect;
  3485. gRect := ForwardRect;
  3486. pbRect := PageBackRect;
  3487. pfRect := PageForwardRect;
  3488. thRect := ThumbRect;
  3489. if PointInRect(Point(X, Y), sRect) then
  3490. begin
  3491. State := sbsBack;
  3492. InvalidateRect(Parent.Handle, @sRect, True);
  3493. Result := True;
  3494. Exit;
  3495. end;
  3496. if PointInRect(Point(X, Y), gRect) then
  3497. begin
  3498. State := sbsForward;
  3499. InvalidateRect(Parent.Handle, @gRect, True);
  3500. Result := True;
  3501. Exit;
  3502. end;
  3503. if PointInRect(Point(X, Y), pbRect) then
  3504. begin
  3505. State := sbsPageBack;
  3506. InvalidateRect(Parent.Handle, @pbRect, True);
  3507. Result := True;
  3508. Exit;
  3509. end;
  3510. if PointInRect(Point(X, Y), pfRect) then
  3511. begin
  3512. State := sbsPageForward;
  3513. InvalidateRect(Parent.Handle, @pfRect, True);
  3514. Result := True;
  3515. Exit;
  3516. end;
  3517. if PointInRect(Point(X, Y), thRect) then
  3518. begin
  3519. State := sbsDragging;
  3520. FXOffset := X - thRect.Left;
  3521. FYOffset := Y - thRect.Top;
  3522. Result := True;
  3523. Exit;
  3524. end;
  3525. end;
  3526. //-------------------- MOUSE UP ----------
  3527. function TGLSMemoScrollBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  3528. Y:
  3529. Integer):
  3530. Boolean;
  3531. var
  3532. sRect, gRect, thRect, pbRect, pfRect: TRect;
  3533. begin
  3534. Result := False;
  3535. if (Width = 0) or (Height = 0) then
  3536. Exit;
  3537. sRect := BackRect;
  3538. gRect := ForwardRect;
  3539. pbRect := PageBackRect;
  3540. pfRect := PageForwardRect;
  3541. thRect := ThumbRect;
  3542. case State of
  3543. sbsBack:
  3544. begin
  3545. State := sbsWait;
  3546. InvalidateRect(Parent.Handle, @sRect, True);
  3547. FParent.DoScroll(Self, -1);
  3548. Result := True;
  3549. Exit;
  3550. end;
  3551. sbsForward:
  3552. begin
  3553. State := sbsWait;
  3554. InvalidateRect(Parent.Handle, @gRect, True);
  3555. FParent.DoScroll(Self, 1);
  3556. Result := True;
  3557. Exit;
  3558. end;
  3559. sbsPageBack:
  3560. begin
  3561. State := sbsWait;
  3562. InvalidateRect(Parent.Handle, @pbRect, True);
  3563. FParent.DoScrollPage(Self, -1);
  3564. Result := True;
  3565. Exit;
  3566. end;
  3567. sbsPageForward:
  3568. begin
  3569. State := sbsWait;
  3570. InvalidateRect(Parent.Handle, @pfRect, True);
  3571. FParent.DoScrollPage(Self, 1);
  3572. Result := True;
  3573. Exit;
  3574. end;
  3575. sbsDragging:
  3576. begin
  3577. State := sbsWait;
  3578. Result := True;
  3579. Exit;
  3580. end;
  3581. end;
  3582. end;
  3583. //-------------------- MOUSE MOVE -----------
  3584. function TGLSMemoScrollBar.MouseMove(Shift: TShiftState; X, Y: Integer):
  3585. Boolean;
  3586. var
  3587. sRect, gRect, thRect, pbRect, pfRect: TRect;
  3588. begin
  3589. Result := False;
  3590. if (Width = 0) or (Height = 0) then
  3591. Exit;
  3592. sRect := BackRect;
  3593. gRect := ForwardRect;
  3594. pbRect := PageBackRect;
  3595. pfRect := PageForwardRect;
  3596. thRect := ThumbRect;
  3597. case State of
  3598. sbsBack:
  3599. if not PointInRect(Point(X, Y), sRect) then
  3600. begin
  3601. State := sbsWait;
  3602. InvalidateRect(Parent.Handle, @sRect, True);
  3603. Result := True;
  3604. Exit;
  3605. end;
  3606. sbsForward:
  3607. if not PointInRect(Point(X, Y), gRect) then
  3608. begin
  3609. State := sbsWait;
  3610. InvalidateRect(Parent.Handle, @gRect, True);
  3611. Result := True;
  3612. Exit;
  3613. end;
  3614. sbsPageBack:
  3615. if not PointInRect(Point(X, Y), pbRect) then
  3616. begin
  3617. State := sbsWait;
  3618. InvalidateRect(Parent.Handle, @pbRect, True);
  3619. Result := True;
  3620. Exit;
  3621. end;
  3622. sbsPageForward:
  3623. if not PointInRect(Point(X, Y), pfRect) then
  3624. begin
  3625. State := sbsWait;
  3626. InvalidateRect(Parent.Handle, @pfRect, True);
  3627. Result := True;
  3628. Exit;
  3629. end;
  3630. sbsDragging:
  3631. begin
  3632. MoveThumbTo(X, Y);
  3633. Result := True;
  3634. Exit;
  3635. end;
  3636. end;
  3637. end;
  3638. //-------------------- MOVE THUMB TO ------------
  3639. function TGLSMemoScrollBar.MoveThumbTo(X, Y: Integer): integer;
  3640. var
  3641. thRect, mRect: TRect;
  3642. FreeLen, ThumbLen, NewPosition, NewOffset: integer;
  3643. begin
  3644. thRect := ThumbRect;
  3645. mRect := MiddleRect;
  3646. NewOffset := 0;
  3647. FreeLen := 0;
  3648. ThumbLen := 0;
  3649. case Kind of
  3650. sbVertical:
  3651. begin
  3652. FreeLen := mRect.Bottom - mRect.Top;
  3653. ThumbLen := thRect.Bottom - thRect.Top;
  3654. NewOffset := Y - FYOffset - (Top + FButtonLength);
  3655. end;
  3656. sbHorizontal:
  3657. begin
  3658. FreeLen := mRect.Right - mRect.Left;
  3659. ThumbLen := thRect.Right - thRect.Left;
  3660. NewOffset := X - FXOffset - (Left + FButtonLength);
  3661. end
  3662. end;
  3663. NewPosition := round(NewOffset * MaxPosition / (FreeLen - ThumbLen));
  3664. Result := NewPosition - Position;
  3665. if NewPosition <> Position then
  3666. begin
  3667. Parent.DoScroll(Self, NewPosition - Position);
  3668. end;
  3669. end;
  3670. //--------------------------------------------------------------
  3671. // GUTTER
  3672. //--------------------------------------------------------------
  3673. //-------------------- SET PARAMS -----------------------
  3674. procedure TGLSMemoGutter.SetParams(Index: integer; Value: integer);
  3675. begin
  3676. case Index of
  3677. 0: FLeft := Value;
  3678. 1: FTop := Value;
  3679. 2: FWidth := Value;
  3680. 3: FHeight := Value;
  3681. end;
  3682. end;
  3683. //-------------------- PAINT TO -----------------------
  3684. procedure TGLSMemoGutter.PaintTo(ACanvas: TCanvas);
  3685. var
  3686. LineNo, T, H: integer;
  3687. begin
  3688. with ACanvas do
  3689. begin
  3690. Pen.Color := clGray;
  3691. MoveTo(Left + Width - 1, Top);
  3692. LineTo(Left + Width - 1, Top + Height);
  3693. Pen.Color := clWhite;
  3694. MoveTo(Left + Width - 2, Top);
  3695. LineTo(Left + Width - 2, Top + Height);
  3696. Brush.Color := Self.FColor;
  3697. FillRect(Rect(Left, Top, Left + Width - 2, Top + Height));
  3698. if Assigned(FMemo.OnGutterDraw) then
  3699. begin
  3700. T := Top;
  3701. H := FMemo.FCellSize.H;
  3702. LineNo := FMemo.FTopLine;
  3703. while T < Top + Height do
  3704. begin
  3705. FMemo.OnGutterDraw(FMemo, ACanvas, LineNo,
  3706. Rect(Left, T, Left + Width - 2, T + H));
  3707. T := T + H;
  3708. Inc(LineNo);
  3709. if LineNo >= FMemo.Lines.Count then
  3710. break;
  3711. end;
  3712. end;
  3713. end;
  3714. end;
  3715. //-------------------- INVALIDATE -----------------------
  3716. procedure TGLSMemoGutter.Invalidate;
  3717. var
  3718. gRect: TRect;
  3719. begin
  3720. gRect := Rect(Left, Top, Left + Width, Top + Height);
  3721. InvalidateRect(FMemo.Handle, @gRect, True);
  3722. end;
  3723. //-------------------- GET RECT -----------------------
  3724. function TGLSMemoGutter.GetRect: TRect;
  3725. begin
  3726. Result := Rect(Left, Top, Left + Width, Top + Height);
  3727. end;
  3728. // ---------------------TStyleList
  3729. procedure TStyleList.CheckRange(Index: integer);
  3730. begin
  3731. if (Index < 0) or (Index >= Count) then
  3732. raise EListError.Create('Incorrect list item index ' + IntToStr(Index));
  3733. end;
  3734. //-------------------- DESTROY ---------------------------
  3735. destructor TStyleList.Destroy;
  3736. begin
  3737. Clear;
  3738. inherited;
  3739. end;
  3740. //-------------------- CHANGE ---------------------------
  3741. procedure TStyleList.Change(Index: integer; ATextColor, ABkCOlor: TColor;
  3742. AStyle: TFontStyles);
  3743. var
  3744. P: TCharStyle;
  3745. begin
  3746. CheckRange(Index);
  3747. P := TCharStyle(Items[Index]);
  3748. P.TextColor := ATextColor;
  3749. P.BkColor := ABkColor;
  3750. P.Style := AStyle;
  3751. end;
  3752. //-------------------- ADD ---------------------------
  3753. function TStyleList.Add(ATextColor, ABkColor: TColor; AStyle: TFontStyles):
  3754. Integer;
  3755. var
  3756. P: TCharStyle;
  3757. begin
  3758. P := TCharStyle.Create;
  3759. with P do
  3760. begin
  3761. TextColor := ATextColor;
  3762. BkColor := ABkColor;
  3763. Style := AStyle;
  3764. end;
  3765. Result := inherited Add(P);
  3766. end;
  3767. //-------------------- CLEAR ---------------------------
  3768. procedure TStyleList.Clear;
  3769. begin
  3770. while Count > 0 do
  3771. Delete(0);
  3772. end;
  3773. //-------------------- DELETE ---------------------------
  3774. procedure TStyleList.Delete(Index: Integer);
  3775. var
  3776. P: TCharStyle;
  3777. begin
  3778. CheckRange(Index);
  3779. P := TCharStyle(Items[Index]);
  3780. P.Free;
  3781. inherited;
  3782. end;
  3783. //-------------------- GET/SET TEXT COLOR ---------------------------
  3784. function TStyleList.GetTextColor(Index: Integer): TColor;
  3785. begin
  3786. CheckRange(Index);
  3787. Result := TCharStyle(Items[Index]).TextColor;
  3788. end;
  3789. procedure TStyleList.SetTextColor(Index: Integer; Value: TColor);
  3790. begin
  3791. CheckRange(Index);
  3792. TCharStyle(Items[Index]).TextColor := Value;
  3793. end;
  3794. //-------------------- GET/SET BK COLOR ---------------------------
  3795. function TStyleList.GetBkColor(Index: Integer): TColor;
  3796. begin
  3797. CheckRange(Index);
  3798. Result := TCharStyle(Items[Index]).BkColor;
  3799. end;
  3800. procedure TStyleList.SetBkColor(Index: Integer; Value: TColor);
  3801. begin
  3802. CheckRange(Index);
  3803. TCharStyle(Items[Index]).BkColor := Value;
  3804. end;
  3805. //-------------------- GET/SET STYLE ---------------------------
  3806. function TStyleList.GetStyle(Index: Integer): TFontStyles;
  3807. begin
  3808. CheckRange(Index);
  3809. Result := TCharStyle(Items[Index]).Style;
  3810. end;
  3811. procedure TStyleList.SetStyle(Index: Integer; Value: TFontStyles);
  3812. begin
  3813. CheckRange(Index);
  3814. TCharStyle(Items[Index]).Style := Value;
  3815. end;
  3816. // ---------------------TGLSMemoStrings
  3817. destructor TGLSMemoStrings.Destroy;
  3818. var
  3819. P: TObject;
  3820. begin
  3821. while Count > 0 do
  3822. begin
  3823. P := inherited GetObject(0);
  3824. P.Free;
  3825. inherited Delete(0);
  3826. end;
  3827. inherited;
  3828. end;
  3829. //-------------------- CLEAR ----------------------
  3830. procedure TGLSMemoStrings.Clear;
  3831. begin
  3832. while Count > 0 do
  3833. begin
  3834. Delete(0);
  3835. if (Count = 1) and (Strings[0] = '') then
  3836. break;
  3837. end;
  3838. end;
  3839. //-------------------- ASSIGN ----------------------
  3840. procedure TGLSMemoStrings.Assign(Source: TPersistent);
  3841. var
  3842. P: TObject;
  3843. begin
  3844. if Source is TStrings then
  3845. begin
  3846. BeginUpdate;
  3847. try
  3848. while Count > 0 do
  3849. begin
  3850. P := inherited GetObject(0);
  3851. P.Free;
  3852. inherited Delete(0);
  3853. end;
  3854. // inherited Clear;
  3855. AddStrings(TStrings(Source));
  3856. finally
  3857. EndUpdate;
  3858. end;
  3859. Exit;
  3860. end;
  3861. inherited Assign(Source);
  3862. end;
  3863. //-------------------- ADD ----------------------
  3864. function TGLSMemoStrings.DoAdd(const S: string): Integer;
  3865. begin
  3866. Result := inherited AddObject(S, nil);
  3867. end;
  3868. //-------------------- ADD ----------------------
  3869. function TGLSMemoStrings.Add(const S: string): Integer;
  3870. begin
  3871. if Assigned(FMemo.Parent) then
  3872. Result := FMemo.AddString(S)
  3873. else
  3874. Result := DoAdd(S);
  3875. end;
  3876. //-------------------- OBJECT ----------------------
  3877. function TGLSMemoStrings.AddObject(const S: string; AObject: TObject): Integer;
  3878. begin
  3879. if AObject <> nil then
  3880. raise EInvalidOp.Create(SObjectsNotSupported);
  3881. Result := DoAdd(S);
  3882. end;
  3883. //-------------------- INSERT ----------------------
  3884. procedure TGLSMemoStrings.InsertObject(Index: Integer;
  3885. const S: string; AObject: TObject);
  3886. begin
  3887. if AObject <> nil then
  3888. raise EInvalidOp.Create(SObjectsNotSupported);
  3889. DoInsert(Index, S);
  3890. end;
  3891. //-------------------- DO INSERT ----------------------
  3892. procedure TGLSMemoStrings.DoInsert(Index: Integer; const S: string);
  3893. begin
  3894. InsertItem(Index, S, nil);
  3895. end;
  3896. //-------------------- INSERT ----------------------
  3897. procedure TGLSMemoStrings.Insert(Index: Integer; const S: string);
  3898. begin
  3899. if Assigned(FMemo) then
  3900. FMemo.InsertString(Index, S)
  3901. else
  3902. DoInsert(Index, S);
  3903. end;
  3904. //-------------------- DELETE ----------------------
  3905. procedure TGLSMemoStrings.Delete(Index: Integer);
  3906. var
  3907. P: TObject;
  3908. begin
  3909. if (Index < 0) or (Index > Count - 1) then
  3910. Exit;
  3911. if FDeleting or (not Assigned(FMemo)) then
  3912. begin
  3913. P := inherited GetObject(Index);
  3914. P.Free;
  3915. inherited;
  3916. end
  3917. else
  3918. begin
  3919. FMemo.DeleteLine(Index, -1, -1, -1, -1, True);
  3920. end;
  3921. end;
  3922. //-------------------- LOAD FROM FILE ----------------------
  3923. procedure TGLSMemoStrings.LoadFromFile(const FileName: string);
  3924. begin
  3925. with FMemo do
  3926. begin
  3927. ClearSelection;
  3928. ClearUndoList;
  3929. CurX := 0;
  3930. CurY := 0;
  3931. end;
  3932. Clear;
  3933. inherited;
  3934. FMemo.Invalidate;
  3935. end;
  3936. //-------------------- SET UPDATE STATE ----------------------
  3937. procedure TGLSMemoStrings.SetUpdateState(Updating: Boolean);
  3938. begin
  3939. if Updating then
  3940. Inc(FLockCount)
  3941. else if FLockCount > 0 then
  3942. Dec(FLockCount);
  3943. end;
  3944. //-------------------- CHECK RANGE ---------------------------
  3945. procedure TGLSMemoStrings.CheckRange(Index: integer);
  3946. begin
  3947. if (Index < 0) or (Index >= Count) then
  3948. raise EListError('Incorrect index of list item ' + IntToStr(Index));
  3949. end;
  3950. //-------------------- GET OBJECT ---------------------------
  3951. function TGLSMemoStrings.GetObject(Index: Integer): TObject;
  3952. begin
  3953. CheckRange(Index);
  3954. Result := inherited GetObject(Index);
  3955. if Assigned(Result) and (Result is TLineProp) then
  3956. Result := TLineProp(Result).FObject;
  3957. end;
  3958. //-------------------- PUT OBJECT ---------------------------
  3959. procedure TGLSMemoStrings.PutObject(Index: Integer; AObject: TObject);
  3960. var
  3961. P: TObject;
  3962. begin
  3963. CheckRange(Index);
  3964. P := Objects[Index];
  3965. if Assigned(P) and (P is TLineProp) then
  3966. TLineProp(P).FObject := AObject
  3967. else
  3968. inherited PutObject(Index, AObject);
  3969. end;
  3970. //-------------------- GET LINE PROP ---------------------------
  3971. function TGLSMemoStrings.GetLineProp(Index: integer): TLineProp;
  3972. var
  3973. P: TObject;
  3974. begin
  3975. CheckRange(Index);
  3976. Result := nil;
  3977. P := inherited GetObject(Index);
  3978. if Assigned(P) and (P is TLineProp) then
  3979. Result := TLineProp(P);
  3980. end;
  3981. //-------------------- CREATE PROP --------------------------
  3982. function TGLSMemoStrings.CreateProp(Index: integer): TLineProp;
  3983. begin
  3984. Result := TLineProp.Create;
  3985. with Result do
  3986. begin
  3987. FStyleNo := 0;
  3988. FInComment := False;
  3989. FInBrackets := -1;
  3990. FValidAttrs := False;
  3991. FCharAttrs := '';
  3992. FObject := Objects[Index];
  3993. end;
  3994. inherited PutObject(Index, Result);
  3995. end;
  3996. //-------------------- GET LINE STYLE --------------------------
  3997. function TGLSMemoStrings.GetLineStyle(Index: integer): integer;
  3998. var
  3999. P: TLineProp;
  4000. begin
  4001. P := LineProp[Index];
  4002. if P = nil then
  4003. Result := 0
  4004. else
  4005. Result := P.FStyleNo;
  4006. end;
  4007. //-------------------- SET LINE STYLE --------------------------
  4008. procedure TGLSMemoStrings.SetLineStyle(Index: integer; Value: integer);
  4009. var
  4010. P: TLineProp;
  4011. begin
  4012. P := LineProp[Index];
  4013. if P = nil then
  4014. P := CreateProp(Index);
  4015. P.FStyleNo := Value;
  4016. end;
  4017. //-------------------- GET/SET IN COMMENT ---------------------------
  4018. function TGLSMemoStrings.GetInComment(Index: Integer): Boolean;
  4019. var
  4020. P: TLineProp;
  4021. begin
  4022. P := LineProp[Index];
  4023. if P = nil then
  4024. Result := False
  4025. else
  4026. Result := P.FInComment;
  4027. end;
  4028. procedure TGLSMemoStrings.SetInComment(Index: Integer; Value: Boolean);
  4029. var
  4030. P: TLineProp;
  4031. begin
  4032. P := LineProp[Index];
  4033. if P = nil then
  4034. P := CreateProp(Index);
  4035. P.FInComment := Value;
  4036. end;
  4037. //-------------------- GET/SET IN BRACKETS ---------------------------
  4038. function TGLSMemoStrings.GetInBrackets(Index: Integer): integer;
  4039. var
  4040. P: TLineProp;
  4041. begin
  4042. P := LineProp[Index];
  4043. if P = nil then
  4044. Result := -1
  4045. else
  4046. Result := P.FInBrackets;
  4047. end;
  4048. procedure TGLSMemoStrings.SetInBrackets(Index: Integer; Value: integer);
  4049. var
  4050. P: TLineProp;
  4051. begin
  4052. P := LineProp[Index];
  4053. if P = nil then
  4054. P := CreateProp(Index);
  4055. P.FInBrackets := Value;
  4056. end;
  4057. //-------------------- GET/SET VALID ATTRS ---------------------------
  4058. function TGLSMemoStrings.GetValidAttrs(Index: Integer): Boolean;
  4059. var
  4060. P: TLineProp;
  4061. begin
  4062. P := LineProp[Index];
  4063. if P = nil then
  4064. Result := False
  4065. else
  4066. Result := P.FValidAttrs;
  4067. end;
  4068. procedure TGLSMemoStrings.SetValidAttrs(Index: Integer; Value: Boolean);
  4069. var
  4070. P: TLineProp;
  4071. begin
  4072. P := LineProp[Index];
  4073. if P = nil then
  4074. P := CreateProp(Index);
  4075. P.FValidAttrs := Value;
  4076. end;
  4077. //-------------------- GET/SET CHAR ATTRS ---------------------------
  4078. function TGLSMemoStrings.GetCharAttrs(Index: Integer): string;
  4079. var
  4080. P: TLineProp;
  4081. begin
  4082. P := LineProp[Index];
  4083. if P = nil then
  4084. Result := ''
  4085. else
  4086. Result := P.FCharAttrs;
  4087. end;
  4088. procedure TGLSMemoStrings.SetCharAttrs(Index: Integer; const Value: string);
  4089. var
  4090. P: TLineProp;
  4091. begin
  4092. P := LineProp[Index];
  4093. if P = nil then
  4094. P := CreateProp(Index);
  4095. P.FCharAttrs := Value;
  4096. end;
  4097. // ---------------------TGLSMemoUndo
  4098. constructor TGLSMemoUndo.Create(ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
  4099. string);
  4100. begin
  4101. inherited Create;
  4102. FUndoCurX0 := ACurX0;
  4103. FUndoCurY0 := ACurY0;
  4104. FUndoCurX := ACurX;
  4105. FUndoCurY := ACurY;
  4106. FUndoText := AText;
  4107. end;
  4108. procedure TGLSMemoUndo.Undo;
  4109. begin
  4110. if Assigned(FMemo) then
  4111. with FMemo do
  4112. begin
  4113. CurY := FUndoCurY;
  4114. CurX := FUndoCurX;
  4115. PerformUndo;
  4116. CurY := FUndoCurY0;
  4117. CurX := FUndoCurX0;
  4118. end;
  4119. end;
  4120. procedure TGLSMemoUndo.Redo;
  4121. begin
  4122. if Assigned(FMemo) then
  4123. with FMemo do
  4124. begin
  4125. CurY := FUndoCurY0;
  4126. CurX := FUndoCurX0;
  4127. PerformRedo;
  4128. CurY := FUndoCurY;
  4129. CurX := FUndoCurX;
  4130. end;
  4131. end;
  4132. function TGLSMemoUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
  4133. begin
  4134. Result := False;
  4135. end;
  4136. //---------------- TINSERT CHAR UNDO --------------------------
  4137. procedure TGLSMemoInsCharUndo.PerformUndo;
  4138. var
  4139. i: integer;
  4140. CurrLine: string;
  4141. begin
  4142. for i := Length(FUndoText) downto 1 do
  4143. begin
  4144. CurrLine := FMemo.Lines[FMemo.CurY];
  4145. if ((FUndoText[i] = #13) and (FMemo.CurX = 0)) or
  4146. (FUndoText[i] = CurrLine[FMemo.CurX]) then
  4147. FMemo.BackSpace;
  4148. end;
  4149. end;
  4150. procedure TGLSMemoInsCharUndo.PerformRedo;
  4151. var
  4152. i: integer;
  4153. begin
  4154. with FMemo do
  4155. for i := 1 to Length(FUndoText) do
  4156. if FUndoText[i] = #13 then
  4157. NewLine
  4158. else
  4159. InsertChar(FUndoText[i]);
  4160. end;
  4161. function TGLSMemoInsCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
  4162. begin
  4163. Result := False;
  4164. if not ((NewUndo is TGLSMemoInsCharUndo) and
  4165. (NewUndo.UndoCurX0 = FUndoCurX) and
  4166. (NewUndo.UndoCurY0 = FUndoCurY)) then
  4167. Exit;
  4168. FUndoText := FUndoText + NewUndo.FUndoText;
  4169. FUndoCurX := NewUndo.UndoCurX;
  4170. FUndoCurY := NewUndo.UndoCurY;
  4171. Result := True;
  4172. end;
  4173. //---------------- TDELETE CHAR UNDO --------------------------
  4174. procedure TGLSMemoDelCharUndo.PerformUndo;
  4175. var
  4176. i: integer;
  4177. begin
  4178. with FMemo do
  4179. for i := 1 to Length(FUndoText) do
  4180. begin
  4181. if not FIsBackspace then
  4182. begin
  4183. CurY := FUndoCurY0;
  4184. CurX := FUndoCurX0;
  4185. end;
  4186. if FUndoText[i] = #13 then
  4187. NewLine
  4188. else
  4189. InsertChar(FUndoText[i]);
  4190. end;
  4191. end;
  4192. procedure TGLSMemoDelCharUndo.PerformRedo;
  4193. var
  4194. i: integer;
  4195. begin
  4196. with FMemo do
  4197. for i := 1 to Length(FUndoText) do
  4198. if FIsBackspace then
  4199. BackSpace
  4200. else
  4201. DeleteChar(-1, -1);
  4202. end;
  4203. function TGLSMemoDelCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
  4204. begin
  4205. Result := False;
  4206. if not ((NewUndo is TGLSMemoDelCharUndo) and
  4207. (NewUndo.UndoCurX0 = FUndoCurX) and
  4208. (NewUndo.UndoCurY0 = FUndoCurY)) then
  4209. Exit;
  4210. if TGLSMemoDelCharUndo(NewUndo).FIsBackspace <> FIsBackspace then
  4211. Exit;
  4212. FUndoText := NewUndo.FUndoText + FUndoText;
  4213. FUndoCurX := NewUndo.UndoCurX;
  4214. FUndoCurY := NewUndo.UndoCurY;
  4215. Result := True;
  4216. end;
  4217. //---------------- TDELETE BUF, LINE UNDO --------------------------
  4218. constructor TGLSMemoDelLineUndo.Create(AIndex, ACurX0, ACurY0, ACurX, ACurY:
  4219. integer; const AText: string);
  4220. begin
  4221. inherited Create(ACurX0, ACurY0, ACurX, ACurY, AText);
  4222. FIndex := AIndex;
  4223. end;
  4224. procedure TGLSMemoDelLineUndo.PerformUndo;
  4225. var
  4226. SaveCurX: integer;
  4227. begin
  4228. with FMemo do
  4229. begin
  4230. SaveCurX := CurX;
  4231. CurX := 0;
  4232. ClearSelection;
  4233. SetSelText(PChar(FUndoText + #13#10));
  4234. CurX := SaveCurX;
  4235. end;
  4236. end;
  4237. procedure TGLSMemoDelLineUndo.PerformRedo;
  4238. begin
  4239. FMemo.DeleteLine(FIndex, FUndoCurX0, FUndoCurY0, FUndoCurX, FUndoCurY, True);
  4240. end;
  4241. procedure TGLSMemoDeleteBufUndo.PerformUndo;
  4242. begin
  4243. with FMemo do
  4244. begin
  4245. ClearSelection;
  4246. SetSelText(PChar(FUndoText));
  4247. end;
  4248. end;
  4249. procedure TGLSMemoDeleteBufUndo.PerformRedo;
  4250. begin
  4251. with FMemo do
  4252. begin
  4253. FSelStartX := FUndoSelStartX;
  4254. FSelStartY := FUndoSelStartY;
  4255. FSelEndX := FUndoSelEndX;
  4256. FSelEndY := FUndoSelEndY;
  4257. DeleteSelection(True);
  4258. end;
  4259. end;
  4260. //---------------- TPASTE UNDO --------------------------
  4261. procedure TGLSMemoPasteUndo.PerformUndo;
  4262. begin
  4263. with FMemo do
  4264. begin
  4265. FSelStartX := FUndoCurX0;
  4266. FSelStartY := FUndoCurY0;
  4267. FSelEndX := FUndoCurX;
  4268. FSelEndY := FUndoCurY;
  4269. DeleteSelection(True);
  4270. end;
  4271. end;
  4272. procedure TGLSMemoPasteUndo.PerformRedo;
  4273. begin
  4274. with FMemo do
  4275. begin
  4276. ClearSelection;
  4277. SetSelText(PChar(FUndoText));
  4278. end;
  4279. end;
  4280. //---------------- TUNDO LIST --------------------------
  4281. constructor TGLSMemoUndoList.Create;
  4282. begin
  4283. inherited;
  4284. FPos := 0;
  4285. FIsPerforming := False;
  4286. FLimit := 100;
  4287. end;
  4288. destructor TGLSMemoUndoList.Destroy;
  4289. begin
  4290. Clear;
  4291. inherited;
  4292. end;
  4293. function TGLSMemoUndoList.Get(Index: Integer): TGLSMemoUndo;
  4294. begin
  4295. Result := TGLSMemoUndo(inherited Get(Index));
  4296. end;
  4297. function TGLSMemoUndoList.Add(Item: Pointer): Integer;
  4298. begin
  4299. Result := -1;
  4300. if FIsPerforming then
  4301. begin
  4302. TGLSMemoUndo(Item).Free;
  4303. Exit;
  4304. end;
  4305. if (Count > 0) and
  4306. Items[0].Append(TGLSMemoUndo(Item)) then
  4307. begin
  4308. TGLSMemoUndo(Item).Free;
  4309. Exit;
  4310. end;
  4311. TGLSMemoUndo(Item).FMemo := Self.FMemo;
  4312. if FPos > 0 then
  4313. while FPos > 0 do
  4314. begin
  4315. Delete(0);
  4316. Dec(FPos);
  4317. end;
  4318. Insert(0, Item);
  4319. if Count > FLimit then
  4320. Delete(Count - 1);
  4321. Memo.UndoChange;
  4322. Result := 0;
  4323. end;
  4324. procedure TGLSMemoUndoList.Clear;
  4325. begin
  4326. while Count > 0 do
  4327. Delete(0);
  4328. FPos := 0;
  4329. with Memo do
  4330. if not (csDestroying in ComponentState) then
  4331. UndoChange;
  4332. end;
  4333. procedure TGLSMemoUndoList.Delete(Index: Integer);
  4334. begin
  4335. TGLSMemoUndo(Items[Index]).Free;
  4336. inherited;
  4337. end;
  4338. procedure TGLSMemoUndoList.Undo;
  4339. var
  4340. OldAutoIndent: Boolean;
  4341. begin
  4342. if FPos < Count then
  4343. begin
  4344. OldAutoIndent := Memo.AutoIndent;
  4345. Memo.AutoIndent := False;
  4346. FIsPerforming := True;
  4347. Items[FPos].Undo;
  4348. Inc(FPos);
  4349. FIsPerforming := False;
  4350. Memo.AutoIndent := OldAutoIndent;
  4351. Memo.UndoChange;
  4352. end;
  4353. end;
  4354. procedure TGLSMemoUndoList.Redo;
  4355. var
  4356. OldAutoIndent: Boolean;
  4357. begin
  4358. if FPos > 0 then
  4359. begin
  4360. OldAutoIndent := Memo.AutoIndent;
  4361. Memo.AutoIndent := False;
  4362. FIsPerforming := True;
  4363. Dec(FPos);
  4364. Items[FPos].Redo;
  4365. FIsPerforming := False;
  4366. Memo.AutoIndent := OldAutoIndent;
  4367. Memo.UndoChange;
  4368. end;
  4369. end;
  4370. procedure TGLSMemoUndoList.SetLimit(Value: integer);
  4371. begin
  4372. if FLimit <> Value then
  4373. begin
  4374. if Value <= 0 then
  4375. Value := 10;
  4376. if Value > 0 then
  4377. Value := 100;
  4378. FLimit := Value;
  4379. Clear;
  4380. end;
  4381. end;
  4382. procedure TGLSSynHiMemo.Paint;
  4383. begin
  4384. FIsPainting := True;
  4385. try
  4386. DelimiterStyle := FDelimiterStyle;
  4387. CommentStyle := FCommentStyle;
  4388. NumberStyle := FNumberStyle;
  4389. inherited;
  4390. finally
  4391. FIsPainting := False;
  4392. end;
  4393. end;
  4394. // ---------------------TGLSSynHiMemo
  4395. procedure TGLSSynHiMemo.SetStyle(Index: integer; Value: TCharStyle);
  4396. var
  4397. No: integer;
  4398. eRect: TRect;
  4399. begin
  4400. No := -1;
  4401. case Index of
  4402. 0: No := FDelimiterStyleNo;
  4403. 1: No := FCommentStyleNo;
  4404. 2: No := FNumberStyleNo;
  4405. end;
  4406. with Value do
  4407. Styles.Change(No, TextColor, BkColor, Style);
  4408. if not FIsPainting then
  4409. begin
  4410. eRect := EditorRect;
  4411. InvalidateRect(Handle, @eRect, True);
  4412. end;
  4413. end;
  4414. //--------------------------------------------------------------
  4415. // SYNTAX MEMO - SET WORD LIST
  4416. //--------------------------------------------------------------
  4417. procedure TGLSSynHiMemo.SetWordList(Value: TGLSMemoStringList);
  4418. begin
  4419. FWordList.Assign(Value);
  4420. end;
  4421. procedure TGLSSynHiMemo.SetSpecialList(Value: TGLSMemoStringList);
  4422. begin
  4423. FSpecialList.Assign(Value);
  4424. end;
  4425. procedure TGLSSynHiMemo.SetBracketList(Value: TGLSMemoStringList);
  4426. begin
  4427. FBracketList.Assign(Value);
  4428. end;
  4429. //--------------------------------------------------------------
  4430. // SYNTAX MEMO - SET CASE SENSITIVE
  4431. //--------------------------------------------------------------
  4432. procedure TGLSSynHiMemo.SetCaseSensitive(Value: Boolean);
  4433. var
  4434. LineNo: integer;
  4435. begin
  4436. if Value <> FCaseSensitive then
  4437. begin
  4438. FCaseSensitive := Value;
  4439. for LineNo := 0 to Lines.Count - 1 do
  4440. ValidAttrs[LineNo] := False;
  4441. Invalidate;
  4442. end;
  4443. end;
  4444. //--------------------------------------------------------------
  4445. // SYNTAX MEMO - GET TOKEN
  4446. //--------------------------------------------------------------
  4447. function TGLSSynHiMemo.GetToken(const S: string; var From: integer;
  4448. out TokenType: TTokenType; out StyleNo: integer): string;
  4449. var
  4450. i, toStart, toEnd, Len, LenSpec: integer;
  4451. Done: Boolean;
  4452. Brackets: string;
  4453. IntPart: integer;
  4454. WasPoint: Boolean;
  4455. //-------------------------------------------------------------
  4456. function StartsFrom(const S: string; Pos: integer; const S0: string): Boolean;
  4457. begin
  4458. Result := (StrLComp(PChar(S) + Pos - 1, PChar(S0), Length(S0)) = 0);
  4459. end;
  4460. //-------------------------------------------------------------
  4461. function Equal(const s1, s2: string): Boolean;
  4462. begin
  4463. if FCaseSensitive then
  4464. Result := s1 = s2
  4465. else
  4466. Result := AnsiLowerCase(s1) = AnsiLowerCase(s2);
  4467. end;
  4468. begin
  4469. toStart := From;
  4470. toEnd := From;
  4471. TokenType := ttOther;
  4472. StyleNo := 0;
  4473. Len := Length(S);
  4474. // End of line
  4475. if From > Len then
  4476. begin
  4477. From := -1;
  4478. Result := '';
  4479. TokenType := ttEOL;
  4480. StyleNo := 0;
  4481. Exit;
  4482. end;
  4483. // Begin of multiline comment
  4484. if (MultiCommentLeft <> '') and (MultiCommentRight <> '') and
  4485. StartsFrom(S, From, MultiCommentLeft) then
  4486. begin
  4487. Result := MultiCommentLeft;
  4488. FInComment := True;
  4489. TokenType := ttComment;
  4490. StyleNo := FCommentStyleNo;
  4491. Inc(From, Length(MultiCommentLeft));
  4492. Exit;
  4493. end;
  4494. // Inside multiline comment
  4495. if FInComment then
  4496. begin
  4497. toEnd := toStart;
  4498. while (toEnd <= Len) and (not StartsFrom(S, toEnd, MultiCommentRight)) do
  4499. Inc(toEnd);
  4500. if toEnd > Len then
  4501. begin
  4502. Result := Copy(S, From, toEnd - From);
  4503. From := toEnd;
  4504. end
  4505. else
  4506. begin
  4507. FInComment := False;
  4508. toEnd := toEnd + Length(MultiCommentRight);
  4509. Result := Copy(S, From, toEnd - From);
  4510. From := toEnd;
  4511. end;
  4512. TokenType := ttComment;
  4513. StyleNo := FCommentStyleNo;
  4514. Exit;
  4515. end;
  4516. // Inside brikets
  4517. if FInBrackets >= 0 then
  4518. begin
  4519. Brackets := FBracketList[FInBrackets];
  4520. toEnd := toStart + 1;
  4521. while (toEnd <= Len) and (S[toEnd] <> Brackets[2]) do
  4522. Inc(toEnd);
  4523. StyleNo := integer(FBracketList.Objects[FInBrackets]);
  4524. if toEnd <= Len then
  4525. begin
  4526. FInBrackets := -1;
  4527. From := toEnd + 1;
  4528. end
  4529. else
  4530. From := toEnd;
  4531. Result := Copy(S, toStart, toEnd - toStart + 1);
  4532. TokenType := ttBracket;
  4533. Exit;
  4534. end;
  4535. // Spaces
  4536. while (toStart <= Len) and (S[toStart] = ' ') do
  4537. Inc(toStart);
  4538. if toStart > From then
  4539. begin
  4540. Result := Copy(S, From, toStart - From);
  4541. From := toStart;
  4542. TokenType := ttSpace;
  4543. StyleNo := 0;
  4544. Exit;
  4545. end;
  4546. // Comment
  4547. if (FLineComment <> '') and StartsFrom(S, From, FLineComment) then
  4548. begin
  4549. Result := Copy(S, From, Len);
  4550. From := Len + 1;
  4551. TokenType := ttComment;
  4552. StyleNo := FCommentStyleNo;
  4553. Exit;
  4554. end;
  4555. // Special keyword
  4556. Done := False;
  4557. for i := 0 to FSpecialList.Count - 1 do
  4558. begin
  4559. LenSpec := Length(FSpecialList[i]);
  4560. if StrLComp(PChar(S) + toStart - 1,
  4561. PChar(FSpecialList[i]), LenSpec) = 0 then
  4562. begin
  4563. toEnd := toStart + LenSpec - 1;
  4564. StyleNo := integer(FSpecialList.Objects[i]);
  4565. TokenType := ttSpecial;
  4566. From := toEnd + 1;
  4567. Done := True;
  4568. break;
  4569. end;
  4570. end;
  4571. // Brickets
  4572. if not Done then
  4573. begin
  4574. for i := 0 to FBracketList.Count - 1 do
  4575. begin
  4576. Brackets := FBracketList[i];
  4577. if S[toStart] = Brackets[1] then
  4578. begin
  4579. FInBrackets := i;
  4580. toEnd := toStart + 1;
  4581. while (toEnd <= Len) and (S[toEnd] <> Brackets[2]) do
  4582. Inc(toEnd);
  4583. if toEnd <= Len then
  4584. FInBrackets := -1
  4585. else
  4586. Dec(toEnd);
  4587. StyleNo := integer(FBracketList.Objects[i]);
  4588. TokenType := ttBracket;
  4589. Done := True;
  4590. break;
  4591. end;
  4592. end;
  4593. end;
  4594. // Delimeters
  4595. if not Done and CharInSet(S[toStart], Delimiters) then
  4596. begin
  4597. toEnd := toStart;
  4598. StyleNo := FDelimiterStyleNo;
  4599. TokenType := ttDelimiter;
  4600. Done := True;
  4601. end;
  4602. // --- Integer or float type
  4603. if not Done and CharInSet(S[toStart], ['0'..'9', '.']) then
  4604. begin
  4605. IntPart := 0;
  4606. WasPoint := False;
  4607. toEnd := toStart;
  4608. Done := True;
  4609. TokenType := ttInteger;
  4610. StyleNo := FNumberStyleNo;
  4611. while (toEnd <= Len) and CharInSet(S[toEnd], ['0'..'9', '.']) do
  4612. begin
  4613. if S[toEnd] = '.' then
  4614. begin
  4615. if not WasPoint then
  4616. begin
  4617. WasPoint := True;
  4618. TokenType := ttFloat;
  4619. end
  4620. else
  4621. begin
  4622. TokenType := ttWrongNumber;
  4623. Color := clRed;
  4624. end;
  4625. end
  4626. else if not WasPoint then
  4627. try
  4628. IntPart := IntPart * 10 + Ord(S[toEnd]) - Ord('0');
  4629. except
  4630. IntPart := MaxInt;
  4631. end;
  4632. Inc(toEnd);
  4633. end;
  4634. Dec(toEnd);
  4635. end;
  4636. // Select word
  4637. if not Done then
  4638. begin
  4639. toEnd := toStart;
  4640. while (toEnd <= Len) and not CharInSet(S[toEnd], Delimiters) do
  4641. Inc(toEnd);
  4642. Dec(toEnd);
  4643. end;
  4644. // Find in dictionary
  4645. Result := Copy(S, toStart, toEnd - toStart + 1);
  4646. for i := 0 to FWordList.Count - 1 do
  4647. if Equal(Result, FWordList[i]) then
  4648. begin
  4649. StyleNo := integer(FWordList.Objects[i]);
  4650. TokenType := ttWord;
  4651. break;
  4652. end;
  4653. From := toEnd + 1;
  4654. end;
  4655. //--------------------------------------------------------------
  4656. // SYNTAX MEMO - FIND LINE ATTRS
  4657. //--------------------------------------------------------------
  4658. procedure TGLSSynHiMemo.FindLineAttrs(Sender: TObject; LineNo: integer;
  4659. var Attrs: string);
  4660. var
  4661. i, From, TokenLen: integer;
  4662. S, Token: string;
  4663. TokenType: TTokenType;
  4664. StyleNo, OldInBrackets: integer;
  4665. OldInComment: Boolean;
  4666. begin
  4667. S := Lines[LineNo];
  4668. SetLength(Attrs, Length(S));
  4669. FInComment := InComment[LineNo];
  4670. FInBrackets := InBrackets[LineNo];
  4671. From := 1;
  4672. while True do
  4673. begin
  4674. Token := GetToken(S, From, TokenType, StyleNo);
  4675. if TokenType = ttEOL then
  4676. break;
  4677. TokenLen := Length(Token);
  4678. for i := From - TokenLen to From - 1 do
  4679. Attrs[i] := Char(StyleNo);
  4680. end;
  4681. if LineNo < Lines.Count - 1 then
  4682. begin
  4683. OldInComment := InComment[LineNo + 1];
  4684. OldInBrackets := InBrackets[LineNo + 1];
  4685. if OldInComment <> FInComment then
  4686. begin
  4687. InComment[LineNo + 1] := FInComment;
  4688. ValidAttrs[LineNo + 1] := False;
  4689. end;
  4690. if OldInBrackets <> FInBrackets then
  4691. begin
  4692. InBrackets[LineNo + 1] := FInBrackets;
  4693. ValidAttrs[LineNo + 1] := False;
  4694. end;
  4695. end;
  4696. end;
  4697. //--------------------------------------------------------------
  4698. // SYNTAX MEMO - ADD WORD
  4699. //--------------------------------------------------------------
  4700. procedure TGLSSynHiMemo.AddWord(StyleNo: integer; const ArrS: array of string);
  4701. var
  4702. i: integer;
  4703. begin
  4704. for i := Low(ArrS) to high(ArrS) do
  4705. FWordList.AddObject(ArrS[i], TObject(StyleNo));
  4706. end;
  4707. //--------------------------------------------------------------
  4708. // SYNTAX MEMO - ADD SPECIAL
  4709. //--------------------------------------------------------------
  4710. procedure TGLSSynHiMemo.AddSpecial(StyleNo: integer; const ArrS: array of string);
  4711. var
  4712. i: integer;
  4713. begin
  4714. for i := Low(ArrS) to high(ArrS) do
  4715. FSpecialList.AddObject(ArrS[i], TObject(StyleNo));
  4716. end;
  4717. //--------------------------------------------------------------
  4718. // SYNTAX MEMO - ADD BRACKETS
  4719. //--------------------------------------------------------------
  4720. procedure TGLSSynHiMemo.AddBrackets(StyleNo: integer; const ArrS: array of string);
  4721. var
  4722. i: integer;
  4723. begin
  4724. for i := Low(ArrS) to high(ArrS) do
  4725. FBracketList.AddObject(ArrS[i], TObject(StyleNo));
  4726. end;
  4727. //--------------------------------------------------------------
  4728. // SYNTAX MEMO - CREATE
  4729. //--------------------------------------------------------------
  4730. constructor TGLSSynHiMemo.Create(AOwner: TComponent);
  4731. begin
  4732. inherited;
  4733. FInBrackets := -1;
  4734. FIsPainting := False;
  4735. FInComment := False;
  4736. FWordList := TGLSMemoStringList.Create;
  4737. FSpecialList := TGLSMemoStringList.Create;
  4738. FBracketList := TGLSMemoStringList.Create;
  4739. FDelimiterStyle := TCharStyle.Create;
  4740. with FDelimiterStyle do
  4741. begin
  4742. TextColor := clBlue;
  4743. BkColor := clWhite;
  4744. Style := [];
  4745. end;
  4746. FCommentStyle := TCharStyle.Create;
  4747. with FCommentStyle do
  4748. begin
  4749. TextColor := clYellow;
  4750. BkColor := clSkyBlue;
  4751. Style := [fsItalic];
  4752. end;
  4753. FNumberStyle := TCharStyle.Create;
  4754. with FNumberStyle do
  4755. begin
  4756. TextColor := clNavy;
  4757. BkColor := clWhite;
  4758. Style := [fsBold];
  4759. end;
  4760. FDelimiterStyleNo := Styles.Add(clBlue, clWhite, []);
  4761. FCommentStyleNo := Styles.Add(clSilver, clWhite, [fsItalic]);
  4762. FNumberStyleNo := Styles.Add(clNavy, clWhite, [fsBold]);
  4763. OnGetLineAttrs := FindLineAttrs;
  4764. Delimiters := [' ', ',', ';', ':', '.', '(', ')', '{', '}', '[', ']',
  4765. '=', '+', '-', '*', '/', '^', '%', '<', '>',
  4766. '"', '''', #13, #10];
  4767. end;
  4768. //--------------------------------------------------------------
  4769. // SYNTAX MEMO - DESTROY
  4770. //--------------------------------------------------------------
  4771. destructor TGLSSynHiMemo.Destroy;
  4772. begin
  4773. FWordList.Free;
  4774. FSpecialList.Free;
  4775. FBracketList.Free;
  4776. FDelimiterStyle.Free;
  4777. FCommentStyle.Free;
  4778. FNumberStyle.Free;
  4779. inherited;
  4780. end;
  4781. // ---------------------TGLSMemoStringList
  4782. procedure TGLSMemoStringList.ReadStrings(Reader: TReader);
  4783. var
  4784. i: Integer;
  4785. begin
  4786. try
  4787. Reader.ReadListBegin;
  4788. Clear;
  4789. while not Reader.EndOfList do
  4790. begin
  4791. i := Add(Reader.ReadString);
  4792. Objects[i] := TObject(Reader.ReadInteger);
  4793. end;
  4794. Reader.ReadListEnd;
  4795. finally
  4796. end;
  4797. end;
  4798. //--------------------------------------------------------------
  4799. // STRING LIST - WRITE STRINGS
  4800. //--------------------------------------------------------------
  4801. procedure TGLSMemoStringList.WriteStrings(Writer: TWriter);
  4802. var
  4803. i: Integer;
  4804. begin
  4805. with Writer do
  4806. begin
  4807. WriteListBegin;
  4808. for i := 0 to Count - 1 do
  4809. begin
  4810. WriteString(Strings[i]);
  4811. WriteInteger(Integer(Objects[i]));
  4812. end;
  4813. WriteListEnd;
  4814. end;
  4815. end;
  4816. //--------------------------------------------------------------
  4817. // STRING LIST - DEFINE PROPERTIES
  4818. //--------------------------------------------------------------
  4819. procedure TGLSMemoStringList.DefineProperties(Filer: TFiler);
  4820. begin
  4821. Filer.DefineProperty('Strings', ReadStrings, WriteStrings, Count > 0);
  4822. end;
  4823. // ---------------------ScrollBar bitmaps
  4824. procedure CreateScrollBarBitmaps;
  4825. var
  4826. i, j: integer;
  4827. begin
  4828. bmScrollBarFill := TBitmap.Create;
  4829. with bmScrollBarFill, Canvas do
  4830. begin
  4831. Width := 8;
  4832. Height := 8;
  4833. Transparent := False;
  4834. for i := 0 to 7 do
  4835. for j := 0 to 7 do
  4836. if Odd(i + j) then
  4837. Pixels[i, j] := clSilver;
  4838. end;
  4839. bmScrollBarUp := TBitmap.Create;
  4840. with bmScrollBarUp, Canvas do
  4841. begin
  4842. Width := 7;
  4843. Height := 8;
  4844. Brush.Color := clSilver;
  4845. FillRect(Rect(0, 0, Width, Height));
  4846. Pixels[3, 2] := clBlack;
  4847. MoveTo(2, 3);
  4848. LineTo(5, 3);
  4849. MoveTo(1, 4);
  4850. LineTo(6, 4);
  4851. MoveTo(0, 5);
  4852. LineTo(7, 5);
  4853. end;
  4854. bmScrollBarDown := TBitmap.Create;
  4855. with bmScrollBarDown, Canvas do
  4856. begin
  4857. Width := 7;
  4858. Height := 8;
  4859. Brush.Color := clSilver;
  4860. FillRect(Rect(0, 0, Width, Height));
  4861. MoveTo(0, 2);
  4862. LineTo(7, 2);
  4863. MoveTo(1, 3);
  4864. LineTo(6, 3);
  4865. MoveTo(2, 4);
  4866. LineTo(5, 4);
  4867. Pixels[3, 5] := clBlack;
  4868. end;
  4869. bmScrollBarLeft := TBitmap.Create;
  4870. with bmScrollBarLeft, Canvas do
  4871. begin
  4872. Width := 8;
  4873. Height := 7;
  4874. Brush.Color := clSilver;
  4875. FillRect(Rect(0, 0, Width, Height));
  4876. Pixels[2, 3] := clBlack;
  4877. MoveTo(3, 2);
  4878. LineTo(3, 5);
  4879. MoveTo(4, 1);
  4880. LineTo(4, 6);
  4881. MoveTo(5, 0);
  4882. LineTo(5, 7);
  4883. end;
  4884. bmScrollBarRight := TBitmap.Create;
  4885. with bmScrollBarRight, Canvas do
  4886. begin
  4887. Width := 8;
  4888. Height := 7;
  4889. Brush.Color := clSilver;
  4890. FillRect(Rect(0, 0, Width, Height));
  4891. MoveTo(2, 0);
  4892. LineTo(2, 7);
  4893. MoveTo(3, 1);
  4894. LineTo(3, 6);
  4895. MoveTo(4, 2);
  4896. LineTo(4, 5);
  4897. Pixels[5, 3] := clBlack;
  4898. end;
  4899. end;
  4900. //------------------ FREE SCROLL BAR BITMAPs -------------------
  4901. procedure FreeScrollBarBitmaps;
  4902. begin
  4903. bmScrollBarFill.Free;
  4904. bmScrollBarUp.Free;
  4905. bmScrollBarDown.Free;
  4906. bmScrollBarLeft.Free;
  4907. bmScrollBarRight.Free;
  4908. end;
  4909. //----------------------------------
  4910. initialization
  4911. //----------------------------------
  4912. RegisterClasses([TGLSSynHiMemo]);
  4913. CreateScrollBarBitmaps;
  4914. IntelliMouseInit;
  4915. //----------------------------------
  4916. finalization
  4917. //----------------------------------
  4918. FreeScrollBarBitmaps;
  4919. end.