editors.pas 116 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797
  1. unit Editors;
  2. {$i platform.inc}
  3. {$ifdef PPC_FPC}
  4. {$H-}
  5. {$else}
  6. {$F+,O+,E+,N+}
  7. {$endif}
  8. {$X+,R-,I-,Q-,V-}
  9. {$ifndef OS_UNIX}
  10. {$S-}
  11. {$endif}
  12. {$define UNIXLF}
  13. {2.0 compatibility}
  14. {$ifdef VER2_0}
  15. {$macro on}
  16. {$define resourcestring := const}
  17. {$endif}
  18. interface
  19. uses
  20. Objects, Drivers,Views,Dialogs,FVCommon,FVConsts;
  21. const
  22. { Length constants. }
  23. Tab_Stop_Length = 74;
  24. {$ifdef PPC_BP}
  25. MaxLineLength = 1024;
  26. MinBufLength = $1000;
  27. MaxBufLength = $ff00;
  28. NotFoundValue = $ffff;
  29. LineInfoGrow = 256;
  30. MaxLines = 16000;
  31. {$else}
  32. MaxLineLength = 4096;
  33. MinBufLength = $1000;
  34. MaxBufLength = $7fffff00;
  35. NotFoundValue = $ffffffff;
  36. LineInfoGrow = 1024;
  37. MaxLines = $7ffffff;
  38. {$endif}
  39. { Editor constants for dialog boxes. }
  40. edOutOfMemory = 0;
  41. edReadError = 1;
  42. edWriteError = 2;
  43. edCreateError = 3;
  44. edSaveModify = 4;
  45. edSaveUntitled = 5;
  46. edSaveAs = 6;
  47. edFind = 7;
  48. edSearchFailed = 8;
  49. edReplace = 9;
  50. edReplacePrompt = 10;
  51. edJumpToLine = 11;
  52. edPasteNotPossible = 12;
  53. edReformatDocument = 13;
  54. edReformatNotAllowed = 14;
  55. edReformNotPossible = 15;
  56. edReplaceNotPossible = 16;
  57. edRightMargin = 17;
  58. edSetTabStops = 18;
  59. edWrapNotPossible = 19;
  60. { Editor flag constants for dialog options. }
  61. efCaseSensitive = $0001;
  62. efWholeWordsOnly = $0002;
  63. efPromptOnReplace = $0004;
  64. efReplaceAll = $0008;
  65. efDoReplace = $0010;
  66. efBackupFiles = $0100;
  67. { Constants for object palettes. }
  68. CIndicator = #2#3;
  69. CEditor = #6#7;
  70. CMemo = #26#27;
  71. type
  72. TEditorDialog = function (Dialog : Integer; Info : Pointer) : Word;
  73. PIndicator = ^TIndicator;
  74. TIndicator = object (TView)
  75. Location : Objects.TPoint;
  76. Modified : Boolean;
  77. AutoIndent : Boolean; { Added boolean for AutoIndent mode. }
  78. WordWrap : Boolean; { Added boolean for WordWrap mode. }
  79. constructor Init (var Bounds : TRect);
  80. procedure Draw; virtual;
  81. function GetPalette : PPalette; virtual;
  82. procedure SetState (AState : Word; Enable : Boolean); virtual;
  83. procedure SetValue (ALocation : Objects.TPoint; IsAutoIndent : Boolean;
  84. IsModified : Boolean;
  85. IsWordWrap : Boolean);
  86. end;
  87. TLineInfoRec = record
  88. Len,Attr : Sw_word;
  89. end;
  90. TLineInfoArr = array[0..MaxLines] of TLineInfoRec;
  91. PLineInfoArr = ^TLineInfoArr;
  92. PLineInfo = ^TLineInfo;
  93. TLineInfo = object
  94. Info : PLineInfoArr;
  95. MaxPos : Sw_Word;
  96. constructor Init;
  97. destructor Done;
  98. procedure Grow(pos:Sw_word);
  99. procedure SetLen(pos,val:Sw_Word);
  100. procedure SetAttr(pos,val:Sw_Word);
  101. function GetLen(pos:Sw_Word):Sw_Word;
  102. function GetAttr(pos:Sw_Word):Sw_Word;
  103. end;
  104. PEditBuffer = ^TEditBuffer;
  105. TEditBuffer = array[0..MaxBufLength] of Char;
  106. PEditor = ^TEditor;
  107. TEditor = object (TView)
  108. HScrollBar : PScrollBar;
  109. VScrollBar : PScrollBar;
  110. Indicator : PIndicator;
  111. Buffer : PEditBuffer;
  112. BufSize : Sw_Word;
  113. BufLen : Sw_Word;
  114. GapLen : Sw_Word;
  115. SelStart : Sw_Word;
  116. SelEnd : Sw_Word;
  117. CurPtr : Sw_Word;
  118. CurPos : Objects.TPoint;
  119. Delta : Objects.TPoint;
  120. Limit : Objects.TPoint;
  121. DrawLine : Sw_Integer;
  122. DrawPtr : Sw_Word;
  123. DelCount : Sw_Word;
  124. InsCount : Sw_Word;
  125. Flags : Longint;
  126. IsReadOnly : Boolean;
  127. IsValid : Boolean;
  128. CanUndo : Boolean;
  129. Modified : Boolean;
  130. Selecting : Boolean;
  131. Overwrite : Boolean;
  132. AutoIndent : Boolean;
  133. NoSelect : Boolean;
  134. TabSize : Sw_Word; { tabsize for displaying }
  135. BlankLine : Sw_Word; { First blank line after a paragraph. }
  136. Word_Wrap : Boolean; { Added boolean to toggle wordwrap on/off. }
  137. Line_Number : string[8]; { Holds line number to jump to. }
  138. Right_Margin : Sw_Integer; { Added integer to set right margin. }
  139. Tab_Settings : String[Tab_Stop_Length]; { Added string to hold tab stops. }
  140. constructor Init (var Bounds : TRect; AHScrollBar, AVScrollBar : PScrollBar;
  141. AIndicator : PIndicator; ABufSize : Sw_Word);
  142. constructor Load (var S : Objects.TStream);
  143. destructor Done; virtual;
  144. function BufChar (P : Sw_Word) : Char;
  145. function BufPtr (P : Sw_Word) : Sw_Word;
  146. procedure ChangeBounds (var Bounds : TRect); virtual;
  147. procedure ConvertEvent (var Event : Drivers.TEvent); virtual;
  148. function CursorVisible : Boolean;
  149. procedure DeleteSelect;
  150. procedure DoneBuffer; virtual;
  151. procedure Draw; virtual;
  152. procedure FormatLine (var DrawBuf; LinePtr : Sw_Word; Width : Sw_Integer; Colors : Word);virtual;
  153. function GetPalette : PPalette; virtual;
  154. procedure HandleEvent (var Event : Drivers.TEvent); virtual;
  155. procedure InitBuffer; virtual;
  156. function InsertBuffer (var P : PEditBuffer; Offset, Length : Sw_Word;AllowUndo, SelectText : Boolean) : Boolean;
  157. function InsertFrom (Editor : PEditor) : Boolean; virtual;
  158. function InsertText (Text : Pointer; Length : Sw_Word; SelectText : Boolean) : Boolean;
  159. procedure ScrollTo (X, Y : Sw_Integer);
  160. function Search (const FindStr : String; Opts : Word) : Boolean;
  161. function SetBufSize (NewSize : Sw_Word) : Boolean; virtual;
  162. procedure SetCmdState (Command : Word; Enable : Boolean);
  163. procedure SetSelect (NewStart, NewEnd : Sw_Word; CurStart : Boolean);
  164. procedure SetCurPtr (P : Sw_Word; SelectMode : Byte);
  165. procedure SetState (AState : Word; Enable : Boolean); virtual;
  166. procedure Store (var S : Objects.TStream);
  167. procedure TrackCursor (Center : Boolean);
  168. procedure Undo;
  169. procedure UpdateCommands; virtual;
  170. function Valid (Command : Word) : Boolean; virtual;
  171. private
  172. KeyState : Integer;
  173. LockCount : Byte;
  174. UpdateFlags : Byte;
  175. Place_Marker : Array [1..10] of Sw_Word; { Inserted array to hold place markers. }
  176. Search_Replace : Boolean; { Added boolean to test for Search and Replace insertions. }
  177. procedure Center_Text (Select_Mode : Byte);
  178. function CharPos (P, Target : Sw_Word) : Sw_Integer;
  179. function CharPtr (P : Sw_Word; Target : Sw_Integer) : Sw_Word;
  180. procedure Check_For_Word_Wrap (Select_Mode : Byte; Center_Cursor : Boolean);
  181. function ClipCopy : Boolean;
  182. procedure ClipCut;
  183. procedure ClipPaste;
  184. procedure DeleteRange (StartPtr, EndPtr : Sw_Word; DelSelect : Boolean);
  185. procedure DoSearchReplace;
  186. procedure DoUpdate;
  187. function Do_Word_Wrap (Select_Mode : Byte; Center_Cursor : Boolean) : Boolean;
  188. procedure DrawLines (Y, Count : Sw_Integer; LinePtr : Sw_Word);
  189. procedure Find;
  190. function GetMousePtr (Mouse : Objects.TPoint) : Sw_Word;
  191. function HasSelection : Boolean;
  192. procedure HideSelect;
  193. procedure Insert_Line (Select_Mode : Byte);
  194. function IsClipboard : Boolean;
  195. procedure Jump_Place_Marker (Element : Byte; Select_Mode : Byte);
  196. procedure Jump_To_Line (Select_Mode : Byte);
  197. function LineEnd (P : Sw_Word) : Sw_Word;
  198. function LineMove (P : Sw_Word; Count : Sw_Integer) : Sw_Word;
  199. function LineStart (P : Sw_Word) : Sw_Word;
  200. function LineNr (P : Sw_Word) : Sw_Word;
  201. procedure Lock;
  202. function NewLine (Select_Mode : Byte) : Boolean;
  203. function NextChar (P : Sw_Word) : Sw_Word;
  204. function NextLine (P : Sw_Word) : Sw_Word;
  205. function NextWord (P : Sw_Word) : Sw_Word;
  206. function PrevChar (P : Sw_Word) : Sw_Word;
  207. function PrevLine (P : Sw_Word) : Sw_Word;
  208. function PrevWord (P : Sw_Word) : Sw_Word;
  209. procedure Reformat_Document (Select_Mode : Byte; Center_Cursor : Boolean);
  210. function Reformat_Paragraph (Select_Mode : Byte; Center_Cursor : Boolean) : Boolean;
  211. procedure Remove_EOL_Spaces (Select_Mode : Byte);
  212. procedure Replace;
  213. procedure Scroll_Down;
  214. procedure Scroll_Up;
  215. procedure Select_Word;
  216. procedure SetBufLen (Length : Sw_Word);
  217. procedure Set_Place_Marker (Element : Byte);
  218. procedure Set_Right_Margin;
  219. procedure Set_Tabs;
  220. procedure StartSelect;
  221. procedure Tab_Key (Select_Mode : Byte);
  222. procedure ToggleInsMode;
  223. procedure Unlock;
  224. procedure Update (AFlags : Byte);
  225. procedure Update_Place_Markers (AddCount : Word; KillCount : Word; StartPtr,EndPtr : Sw_Word);
  226. end;
  227. TMemoData = record
  228. Length : Sw_Word;
  229. Buffer : TEditBuffer;
  230. end;
  231. PMemo = ^TMemo;
  232. TMemo = object (TEditor)
  233. constructor Load (var S : Objects.TStream);
  234. function DataSize : Sw_Word; virtual;
  235. procedure GetData (var Rec); virtual;
  236. function GetPalette : PPalette; virtual;
  237. procedure HandleEvent (var Event : Drivers.TEvent); virtual;
  238. procedure SetData (var Rec); virtual;
  239. procedure Store (var S : Objects.TStream);
  240. end;
  241. PFileEditor = ^TFileEditor;
  242. TFileEditor = object (TEditor)
  243. FileName : FNameStr;
  244. constructor Init (var Bounds : TRect; AHScrollBar, AVScrollBar : PScrollBar;
  245. AIndicator : PIndicator; AFileName : FNameStr);
  246. constructor Load (var S : Objects.TStream);
  247. procedure DoneBuffer; virtual;
  248. procedure HandleEvent (var Event : Drivers.TEvent); virtual;
  249. procedure InitBuffer; virtual;
  250. function LoadFile : Boolean;
  251. function Save : Boolean;
  252. function SaveAs : Boolean;
  253. function SaveFile : Boolean;
  254. function SetBufSize (NewSize : Sw_Word) : Boolean; virtual;
  255. procedure Store (var S : Objects.TStream);
  256. procedure UpdateCommands; virtual;
  257. function Valid (Command : Word) : Boolean; virtual;
  258. end;
  259. PEditWindow = ^TEditWindow;
  260. TEditWindow = object (TWindow)
  261. Editor : PFileEditor;
  262. constructor Init (var Bounds : TRect; FileName : FNameStr; ANumber : Integer);
  263. constructor Load (var S : Objects.TStream);
  264. procedure Close; virtual;
  265. function GetTitle (MaxSize : Sw_Integer) : TTitleStr; virtual;
  266. procedure HandleEvent (var Event : Drivers.TEvent); virtual;
  267. procedure SizeLimits(var Min, Max: TPoint); virtual;
  268. procedure Store (var S : Objects.TStream);
  269. end;
  270. function DefEditorDialog (Dialog : Integer; Info : Pointer) : Word;
  271. function CreateFindDialog: PDialog;
  272. function CreateReplaceDialog: PDialog;
  273. function JumpLineDialog : PDialog;
  274. function ReformDocDialog : PDialog;
  275. function RightMarginDialog : PDialog;
  276. function TabStopDialog : Dialogs.PDialog;
  277. function StdEditorDialog(Dialog: Integer; Info: Pointer): Word;
  278. const
  279. WordChars : set of Char = ['!'..#255];
  280. LineBreak : string[2]=
  281. {$ifdef UNIXLF}
  282. #10;
  283. {$else}
  284. #13#10;
  285. {$endif}
  286. { The Allow_Reformat boolean is a programmer hook. }
  287. { I've placed this here to allow programmers to }
  288. { determine whether or not paragraph and document }
  289. { reformatting are allowed if Word_Wrap is not }
  290. { active. Some people say don't allow, and others }
  291. { say allow it. I've left it up to the programmer. }
  292. { Set to FALSE if not allowed, or TRUE if allowed. }
  293. Allow_Reformat : Boolean = True;
  294. EditorDialog : TEditorDialog = {$ifdef fpc}@{$endif}DefEditorDialog;
  295. EditorFlags : Word = efBackupFiles + efPromptOnReplace;
  296. FindStr : String[80] = '';
  297. ReplaceStr : String[80] = '';
  298. Clipboard : PEditor = nil;
  299. ToClipCmds : TCommandSet = ([cmCut,cmCopy,cmClear]);
  300. FromClipCmds : TCommandSet = ([cmPaste]);
  301. UndoCmds : TCommandSet = ([cmUndo,cmRedo]);
  302. TYPE
  303. TFindDialogRec =
  304. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  305. packed
  306. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  307. record
  308. Find : String[80];
  309. Options : Word;
  310. end;
  311. TReplaceDialogRec =
  312. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  313. packed
  314. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  315. record
  316. Find : String[80];
  317. Replace : String[80];
  318. Options : Word;
  319. end;
  320. TRightMarginRec =
  321. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  322. packed
  323. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  324. record
  325. Margin_Position : String[3];
  326. end;
  327. TTabStopRec =
  328. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  329. packed
  330. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  331. record
  332. Tab_String : String [Tab_Stop_Length];
  333. end;
  334. CONST
  335. { VMT constants. }
  336. REditor : TStreamRec = (ObjType : 70;
  337. VmtLink : Ofs (TypeOf (TEditor)^);
  338. Load : @TEditor.Load;
  339. Store : @TEditor.Store);
  340. RMemo : TStreamRec = (ObjType : 71;
  341. VmtLink : Ofs (TypeOf (TMemo)^);
  342. Load : @TMemo.Load;
  343. Store : @TMemo.Store);
  344. RFileEditor : TStreamRec = (ObjType : 72;
  345. VmtLink : Ofs (TypeOf (TFileEditor)^);
  346. Load : @TFileEditor.Load;
  347. Store : @TFileEditor.Store);
  348. RIndicator : TStreamRec = (ObjType : 73;
  349. VmtLink : Ofs (TypeOf (TIndicator)^);
  350. Load : @TIndicator.Load;
  351. Store : @TIndicator.Store);
  352. REditWindow : TStreamRec = (ObjType : 74;
  353. VmtLink : Ofs (TypeOf (TEditWindow)^);
  354. Load : @TEditWindow.Load;
  355. Store : @TEditWindow.Store);
  356. procedure RegisterEditors;
  357. {****************************************************************************
  358. Implementation
  359. ****************************************************************************}
  360. implementation
  361. uses
  362. Dos, App, StdDlg, MsgBox{, Resource};
  363. type
  364. pword = ^word;
  365. resourcestring sClipboard='Clipboard';
  366. sFileCreateError='Error creating file %s';
  367. sFileReadError='Error reading file %s';
  368. sFileUntitled='Save untitled file?';
  369. sFileWriteError='Error writing to file %s';
  370. sFind='Find';
  371. sJumpTo='Jump To';
  372. sModified=''#3'%s'#13#10#13#3'has been modified. Save?';
  373. sOutOfMemory='Not enough memory for this operation.';
  374. sPasteNotPossible='Wordwrap on: Paste not possible in current margins when at end of line.';
  375. sReformatDocument='Reformat Document';
  376. sReformatNotPossible='Paragraph reformat not possible while trying to wrap current line with current margins.';
  377. sReformattingTheDocument='Reformatting the document:';
  378. sReplaceNotPossible='Wordwrap on: Replace not possible in current margins when at end of line.';
  379. sReplaceThisOccurence='Replace this occurence?';
  380. sRightMargin='Right Margin';
  381. sSearchStringNotFound='Search string not found.';
  382. sSelectWhereToBegin='Please select where to begin.';
  383. sSetting='Setting:';
  384. sTabSettings='Tab Settings';
  385. sUnknownDialog='Unknown dialog requested!';
  386. sUntitled='Untitled';
  387. sWordWrapNotPossible='Wordwrap on: Wordwrap not possible in current margins with continuous line.';
  388. sWordWrapOff='You must turn on wordwrap before you can reformat.';
  389. slCaseSensitive='~C~ase sensitive';
  390. slCurrentLine='~C~urrent line';
  391. slEntireDocument='~E~ntire document';
  392. slLineNumber='~L~ine number';
  393. slNewText='~N~ew text';
  394. slPromptOnReplace='~P~rompt on replace';
  395. slReplace='~R~eplace';
  396. slReplaceAll='~R~eplace all';
  397. slTextToFind='~T~ext to find';
  398. slWholeWordsOnly='~W~hole words only';
  399. CONST
  400. { Update flag constants. }
  401. ufUpdate = $01;
  402. ufLine = $02;
  403. ufView = $04;
  404. ufStats = $05;
  405. { SelectMode constants. }
  406. smExtend = $01;
  407. smDouble = $02;
  408. sfSearchFailed = NotFoundValue;
  409. { Arrays that hold all the command keys and options. }
  410. FirstKeys : array[0..46 * 2] of Word = (46, Ord (^A), cmWordLeft,
  411. Ord (^B), cmReformPara,
  412. Ord (^C), cmPageDown,
  413. Ord (^D), cmCharRight,
  414. Ord (^E), cmLineUp,
  415. Ord (^F), cmWordRight,
  416. Ord (^G), cmDelChar,
  417. Ord (^H), cmBackSpace,
  418. Ord (^I), cmTabKey,
  419. Ord (^J), $FF04,
  420. Ord (^K), $FF02,
  421. Ord (^L), cmSearchAgain,
  422. Ord (^M), cmNewLine,
  423. Ord (^N), cmInsertLine,
  424. Ord (^O), $FF03,
  425. Ord (^Q), $FF01,
  426. Ord (^R), cmPageUp,
  427. Ord (^S), cmCharLeft,
  428. Ord (^T), cmDelWord,
  429. Ord (^U), cmUndo,
  430. Ord (^V), cmInsMode,
  431. Ord (^W), cmScrollUp,
  432. Ord (^X), cmLineDown,
  433. Ord (^Y), cmDelLine,
  434. Ord (^Z), cmScrollDown,
  435. kbLeft, cmCharLeft,
  436. kbRight, cmCharRight,
  437. kbCtrlLeft, cmWordLeft,
  438. kbCtrlRight, cmWordRight,
  439. kbHome, cmLineStart,
  440. kbEnd, cmLineEnd,
  441. kbCtrlHome, cmHomePage,
  442. kbCtrlEnd, cmEndPage,
  443. kbUp, cmLineUp,
  444. kbDown, cmLineDown,
  445. kbPgUp, cmPageUp,
  446. kbPgDn, cmPageDown,
  447. kbCtrlPgUp, cmTextStart,
  448. kbCtrlPgDn, cmTextEnd,
  449. kbIns, cmInsMode,
  450. kbDel, cmDelChar,
  451. kbCtrlBack, cmDelStart,
  452. kbShiftIns, cmPaste,
  453. kbShiftDel, cmCut,
  454. kbCtrlIns, cmCopy,
  455. kbCtrlDel, cmClear);
  456. { SCRLUP - Stop. } { Added ^W to scroll screen up. }
  457. { SCRLDN - Stop. } { Added ^Z to scroll screen down. }
  458. { REFORM - Stop. } { Added ^B for paragraph reformatting. }
  459. { PRETAB - Stop. } { Added ^I for preset tabbing. }
  460. { JLINE - Stop. } { Added ^J to jump to a line number. }
  461. { INSLIN - Stop. } { Added ^N to insert line at cursor. }
  462. { INDENT - Stop. } { Removed ^O and put it into ^QI. }
  463. { HOMEND - Stop. } { Added kbCtrlHome and kbCtrlEnd pages. }
  464. { CTRLBK - Stop. } { Added kbCtrlBack same as ^QH. }
  465. QuickKeys : array[0..21 * 2] of Word = (21, Ord ('0'), cmJumpMark0,
  466. Ord ('1'), cmJumpMark1,
  467. Ord ('2'), cmJumpMark2,
  468. Ord ('3'), cmJumpMark3,
  469. Ord ('4'), cmJumpMark4,
  470. Ord ('5'), cmJumpMark5,
  471. Ord ('6'), cmJumpMark6,
  472. Ord ('7'), cmJumpMark7,
  473. Ord ('8'), cmJumpMark8,
  474. Ord ('9'), cmJumpMark9,
  475. Ord ('A'), cmReplace,
  476. Ord ('C'), cmTextEnd,
  477. Ord ('D'), cmLineEnd,
  478. Ord ('F'), cmFind,
  479. Ord ('H'), cmDelStart,
  480. Ord ('I'), cmIndentMode,
  481. Ord ('L'), cmUndo,
  482. Ord ('R'), cmTextStart,
  483. Ord ('S'), cmLineStart,
  484. Ord ('U'), cmReformDoc,
  485. Ord ('Y'), cmDelEnd);
  486. { UNDO - Stop. } { Added IDE undo feature of ^QL. }
  487. { REFDOC - Stop. } { Added document reformat feature if ^QU pressed. }
  488. { MARK - Stop. } { Added cmJumpMark# to allow place marking. }
  489. { INDENT - Stop. } { Moved IndentMode here from Firstkeys. }
  490. BlockKeys : array[0..20 * 2] of Word = (20, Ord ('0'), cmSetMark0,
  491. Ord ('1'), cmSetMark1,
  492. Ord ('2'), cmSetMark2,
  493. Ord ('3'), cmSetMark3,
  494. Ord ('4'), cmSetMark4,
  495. Ord ('5'), cmSetMark5,
  496. Ord ('6'), cmSetMark6,
  497. Ord ('7'), cmSetMark7,
  498. Ord ('8'), cmSetMark8,
  499. Ord ('9'), cmSetMark9,
  500. Ord ('B'), cmStartSelect,
  501. Ord ('C'), cmPaste,
  502. Ord ('D'), cmSave,
  503. Ord ('F'), cmSaveAs,
  504. Ord ('H'), cmHideSelect,
  505. Ord ('K'), cmCopy,
  506. Ord ('S'), cmSave,
  507. Ord ('T'), cmSelectWord,
  508. Ord ('Y'), cmCut,
  509. Ord ('X'), cmSaveDone);
  510. { SELWRD - Stop. } { Added ^KT to select word only. }
  511. { SAVE - Stop. } { Added ^KD, ^KF, ^KS, ^KX key commands. }
  512. { MARK - Stop. } { Added cmSetMark# to allow place marking. }
  513. FormatKeys : array[0..5 * 2] of Word = (5, Ord ('C'), cmCenterText,
  514. Ord ('T'), cmCenterText,
  515. Ord ('I'), cmSetTabs,
  516. Ord ('R'), cmRightMargin,
  517. Ord ('W'), cmWordWrap);
  518. { WRAP - Stop. } { Added Wordwrap feature if ^OW pressed. }
  519. { RMSET - Stop. } { Added set right margin feature if ^OR pressed. }
  520. { PRETAB - Stop. } { Added preset tab feature if ^OI pressed. }
  521. { CENTER - Stop. } { Added center text option ^OC for a line. }
  522. JumpKeys : array[0..1 * 2] of Word = (1, Ord ('L'), cmJumpLine);
  523. { JLINE - Stop. } { Added jump to line number feature if ^JL pressed. }
  524. KeyMap : array[0..4] of Pointer = (@FirstKeys,
  525. @QuickKeys,
  526. @BlockKeys,
  527. @FormatKeys,
  528. @JumpKeys);
  529. { WRAP - Stop. } { Added @FormatKeys for new ^O? keys. }
  530. { PRETAB - Stop. } { Added @FormatKeys for new ^O? keys. }
  531. { JLINE - Stop. } { Added @JumpKeys for new ^J? keys. }
  532. { CENTER - Stop. } { Added @FormatKeys for new ^O? keys. }
  533. {****************************************************************************
  534. Dialogs
  535. ****************************************************************************}
  536. function DefEditorDialog (Dialog : Integer; Info : Pointer) : Word;
  537. begin
  538. DefEditorDialog := cmCancel;
  539. end; { DefEditorDialog }
  540. function CreateFindDialog: PDialog;
  541. var
  542. D: PDialog;
  543. Control: PView;
  544. R: TRect;
  545. begin
  546. R.Assign(0, 0, 38, 12);
  547. D := New(PDialog, Init(R,sFind));
  548. with D^ do
  549. begin
  550. Options := Options or ofCentered;
  551. R.Assign(3, 3, 32, 4);
  552. Control := New(PInputLine, Init(R, 80));
  553. Control^.HelpCtx := hcDFindText;
  554. Insert(Control);
  555. R.Assign(2, 2, 15, 3);
  556. Insert(New(PLabel, Init(R, slTextToFind, Control)));
  557. R.Assign(32, 3, 35, 4);
  558. Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  559. R.Assign(3, 5, 35, 7);
  560. Control := New(PCheckBoxes, Init(R,
  561. NewSItem (slCaseSensitive,
  562. NewSItem (slWholeWordsOnly,nil))));
  563. Control^.HelpCtx := hcCCaseSensitive;
  564. Insert(Control);
  565. R.Assign(14, 9, 24, 11);
  566. Control := New (PButton, Init(R,slOK,cmOk,bfDefault));
  567. Control^.HelpCtx := hcDOk;
  568. Insert (Control);
  569. Inc(R.A.X, 12); Inc(R.B.X, 12);
  570. Control := New (PButton, Init(R,slCancel,cmCancel, bfNormal));
  571. Control^.HelpCtx := hcDCancel;
  572. Insert (Control);
  573. SelectNext(False);
  574. end;
  575. CreateFindDialog := D;
  576. end;
  577. function CreateReplaceDialog: PDialog;
  578. var
  579. D: PDialog;
  580. Control: PView;
  581. R: TRect;
  582. begin
  583. R.Assign(0, 0, 40, 16);
  584. D := New(PDialog, Init(R,slReplace));
  585. with D^ do
  586. begin
  587. Options := Options or ofCentered;
  588. R.Assign(3, 3, 34, 4);
  589. Control := New(PInputLine, Init(R, 80));
  590. Control^.HelpCtx := hcDFindText;
  591. Insert(Control);
  592. R.Assign(2, 2, 15, 3);
  593. Insert(New(PLabel, Init(R,slTextToFind, Control)));
  594. R.Assign(34, 3, 37, 4);
  595. Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  596. R.Assign(3, 6, 34, 7);
  597. Control := New(PInputLine, Init(R, 80));
  598. Control^.HelpCtx := hcDReplaceText;
  599. Insert(Control);
  600. R.Assign(2, 5, 12, 6);
  601. Insert(New(PLabel, Init(R,slNewText, Control)));
  602. R.Assign(34, 6, 37, 7);
  603. Insert(New(PHistory, Init(R, PInputLine(Control), 11)));
  604. R.Assign(3, 8, 37, 12);
  605. Control := New (Dialogs.PCheckBoxes, Init (R,
  606. NewSItem (slCasesensitive,
  607. NewSItem (slWholewordsonly,
  608. NewSItem (slPromptonreplace,
  609. NewSItem (slReplaceall, nil))))));
  610. Control^.HelpCtx := hcCCaseSensitive;
  611. Insert (Control);
  612. R.Assign (8, 13, 18, 15);
  613. Control := New (PButton, Init (R,slOK, cmOk, bfDefault));
  614. Control^.HelpCtx := hcDOk;
  615. Insert (Control);
  616. R.Assign (22, 13, 32, 15);
  617. Control := New (PButton, Init (R,slCancel, cmCancel, bfNormal));
  618. Control^.HelpCtx := hcDCancel;
  619. Insert (Control);
  620. SelectNext(False);
  621. end;
  622. CreateReplaceDialog := D;
  623. end;
  624. function JumpLineDialog : PDialog;
  625. VAR
  626. D : PDialog;
  627. R : TRect;
  628. Control: PView;
  629. Begin
  630. R.Assign (0, 0, 26, 8);
  631. D := New(PDialog, Init(R,sJumpTo));
  632. with D^ do
  633. begin
  634. Options := Options or ofCentered;
  635. R.Assign (3, 2, 15, 3);
  636. Control := New (Dialogs.PStaticText, Init (R,slLineNumber));
  637. Insert (Control);
  638. R.Assign (15, 2, 21, 3);
  639. Control := New (Dialogs.PInputLine, Init (R, 4));
  640. Control^.HelpCtx := hcDLineNumber;
  641. Insert (Control);
  642. R.Assign (21, 2, 24, 3);
  643. Insert (New (Dialogs.PHistory, Init (R, Dialogs.PInputLine (Control), 12)));
  644. R.Assign (2, 5, 12, 7);
  645. Control := New (Dialogs.PButton, Init (R, slOK, cmOK, Dialogs.bfDefault));
  646. Control^.HelpCtx := hcDOk;
  647. Insert (Control);
  648. R.Assign (14, 5, 24, 7);
  649. Control := New (Dialogs.PButton, Init (R, slCancel, cmCancel, Dialogs.bfNormal));
  650. Control^.HelpCtx := hcDCancel;
  651. Insert (Control);
  652. SelectNext (False);
  653. end;
  654. JumpLineDialog := D;
  655. end; { JumpLineDialog }
  656. function ReformDocDialog : Dialogs.PDialog;
  657. { This is a local function that brings up a dialog box }
  658. { that asks where to start reformatting the document. }
  659. VAR
  660. R : TRect;
  661. D : Dialogs.PDialog;
  662. Control : PView;
  663. Begin
  664. R.Assign (0, 0, 32, 11);
  665. D := New (Dialogs.PDialog, Init (R, sReformatDocument));
  666. with D^ do
  667. begin
  668. Options := Options or ofCentered;
  669. R.Assign (2, 2, 30, 3);
  670. Control := New (Dialogs.PStaticText, Init (R, sSelectWhereToBegin));
  671. Insert (Control);
  672. R.Assign (3, 3, 29, 4);
  673. Control := New (Dialogs.PStaticText, Init (R, sReformattingTheDocument));
  674. Insert (Control);
  675. R.Assign (50, 5, 68, 6);
  676. Control := New (Dialogs.PLabel, Init (R, sReformatDocument, Control));
  677. Insert (Control);
  678. R.Assign (5, 5, 26, 7);
  679. Control := New (Dialogs.PRadioButtons, Init (R,
  680. NewSItem (slCurrentLine,
  681. NewSItem (slEntireDocument, Nil))));
  682. Control^.HelpCtx := hcDReformDoc;
  683. Insert (Control);
  684. R.Assign (4, 8, 14, 10);
  685. Control := New (Dialogs.PButton, Init (R, slOK, cmOK, Dialogs.bfDefault));
  686. Control^.HelpCtx := hcDOk;
  687. Insert (Control);
  688. R.Assign (17, 8, 27, 10);
  689. Control := New (Dialogs.PButton, Init (R, slCancel, cmCancel, Dialogs.bfNormal));
  690. Control^.HelpCtx := hcDCancel;
  691. Insert (Control);
  692. SelectNext (False);
  693. end;
  694. ReformDocDialog := D;
  695. end; { ReformDocDialog }
  696. function RightMarginDialog : Dialogs.PDialog;
  697. { This is a local function that brings up a dialog box }
  698. { that allows the user to change the Right_Margin. }
  699. VAR
  700. R : TRect;
  701. D : PDialog;
  702. Control : PView;
  703. Begin
  704. R.Assign (0, 0, 26, 8);
  705. D := New (Dialogs.PDialog, Init (R, sRightMargin));
  706. with D^ do
  707. begin
  708. Options := Options or ofCentered;
  709. R.Assign (5, 2, 13, 3);
  710. Control := New (Dialogs.PStaticText, Init (R, sSetting));
  711. Insert (Control);
  712. R.Assign (13, 2, 18, 3);
  713. Control := New (Dialogs.PInputLine, Init (R, 3));
  714. Control^.HelpCtx := hcDRightMargin;
  715. Insert (Control);
  716. R.Assign (18, 2, 21, 3);
  717. Insert (New (Dialogs.PHistory, Init (R, Dialogs.PInputLine (Control), 13)));
  718. R.Assign (2, 5, 12, 7);
  719. Control := New (Dialogs.PButton, Init (R, slOK, cmOK, Dialogs.bfDefault));
  720. Control^.HelpCtx := hcDOk;
  721. Insert (Control);
  722. R.Assign (14, 5, 24, 7);
  723. Control := New (Dialogs.PButton, Init (R, slCancel, cmCancel, Dialogs.bfNormal));
  724. Control^.HelpCtx := hcDCancel;
  725. Insert (Control);
  726. SelectNext (False);
  727. end;
  728. RightMarginDialog := D;
  729. end; { RightMarginDialog; }
  730. function TabStopDialog : Dialogs.PDialog;
  731. { This is a local function that brings up a dialog box }
  732. { that allows the user to set their own tab stops. }
  733. VAR
  734. Index : Sw_Integer; { Local Indexing variable. }
  735. R : TRect;
  736. D : PDialog;
  737. Control : PView;
  738. Tab_Stop : String[2]; { Local string to print tab column number. }
  739. Begin
  740. R.Assign (0, 0, 80, 8);
  741. D := New (Dialogs.PDialog, Init (R, sTabSettings));
  742. with D^ do
  743. begin
  744. Options := Options or ofCentered;
  745. R.Assign (2, 2, 77, 3);
  746. Control := New (Dialogs.PStaticText, Init (R,
  747. ' ....|....|....|....|....|....|....|....|....|....|....|....|....|....|....'));
  748. Insert (Control);
  749. for Index := 1 to 7 do
  750. begin
  751. R.Assign (Index * 10 + 1, 1, Index * 10 + 3, 2);
  752. Str (Index * 10, Tab_Stop);
  753. Control := New (Dialogs.PStaticText, Init (R, Tab_Stop));
  754. Insert (Control);
  755. end;
  756. R.Assign (2, 3, 78, 4);
  757. Control := New (Dialogs.PInputLine, Init (R, 74));
  758. Control^.HelpCtx := hcDTabStops;
  759. Insert (Control);
  760. R.Assign (38, 5, 41, 6);
  761. Insert (New (Dialogs.PHistory, Init (R, Dialogs.PInputLine (Control), 14)));
  762. R.Assign (27, 5, 37, 7);
  763. Control := New (Dialogs.PButton, Init (R, slOK, cmOK, Dialogs.bfDefault));
  764. Control^.HelpCtx := hcDOk;
  765. Insert (Control);
  766. R.Assign (42, 5, 52, 7);
  767. Control := New (Dialogs.PButton, Init (R, slCancel, cmCancel, Dialogs.bfNormal));
  768. Control^.HelpCtx := hcDCancel;
  769. Insert (Control);
  770. SelectNext (False);
  771. end;
  772. TabStopDialog := D;
  773. end { TabStopDialog };
  774. function StdEditorDialog(Dialog: Integer; Info: Pointer): Word;
  775. var
  776. R: TRect;
  777. T: TPoint;
  778. begin
  779. case Dialog of
  780. edOutOfMemory:
  781. StdEditorDialog := MessageBox(sOutOfMemory, nil, mfError + mfOkButton);
  782. edReadError:
  783. StdEditorDialog := MessageBox(sFileReadError, @Info, mfError + mfOkButton);
  784. edWriteError:
  785. StdEditorDialog := MessageBox(sFileWriteError, @Info, mfError + mfOkButton);
  786. edCreateError:
  787. StdEditorDialog := MessageBox(sFileCreateError, @Info, mfError + mfOkButton);
  788. edSaveModify:
  789. StdEditorDialog := MessageBox(sModified, @Info, mfInformation + mfYesNoCancel);
  790. edSaveUntitled:
  791. StdEditorDialog := MessageBox(sFileUntitled, nil, mfInformation + mfYesNoCancel);
  792. edSaveAs:
  793. StdEditorDialog := Application^.ExecuteDialog(New(PFileDialog, Init('*.*',
  794. slSaveFileAs, slName, fdOkButton, 101)), Info);
  795. edFind:
  796. StdEditorDialog := Application^.ExecuteDialog(CreateFindDialog, Info);
  797. edSearchFailed:
  798. StdEditorDialog := MessageBox(sSearchStringNotFound, nil, mfError + mfOkButton);
  799. edReplace:
  800. StdEditorDialog := Application^.ExecuteDialog(CreateReplaceDialog, Info);
  801. edReplacePrompt:
  802. begin
  803. { Avoid placing the dialog on the same line as the cursor }
  804. R.Assign(0, 1, 40, 8);
  805. R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  806. Desktop^.MakeGlobal(R.B, T);
  807. Inc(T.Y);
  808. if PPoint(Info)^.Y <= T.Y then
  809. R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  810. StdEditorDialog := MessageBoxRect(R, sReplaceThisOccurence,
  811. nil, mfYesNoCancel + mfInformation);
  812. end;
  813. edJumpToLine:
  814. StdEditorDialog := Application^.ExecuteDialog(JumpLineDialog, Info);
  815. edSetTabStops:
  816. StdEditorDialog := Application^.ExecuteDialog(TabStopDialog, Info);
  817. edPasteNotPossible:
  818. StdEditorDialog := MessageBox (sPasteNotPossible, nil, mfError + mfOkButton);
  819. edReformatDocument:
  820. StdEditorDialog := Application^.ExecuteDialog(ReformDocDialog, Info);
  821. edReformatNotAllowed:
  822. StdEditorDialog := MessageBox (sWordWrapOff, nil, mfError + mfOkButton);
  823. edReformNotPossible:
  824. StdEditorDialog := MessageBox (sReformatNotPossible, nil, mfError + mfOkButton);
  825. edReplaceNotPossible:
  826. StdEditorDialog := MessageBox (sReplaceNotPossible, nil, mfError + mfOkButton);
  827. edRightMargin:
  828. StdEditorDialog := Application^.ExecuteDialog(RightMarginDialog, Info);
  829. edWrapNotPossible:
  830. StdEditorDialog := MessageBox (sWordWrapNotPossible, nil, mfError + mfOKButton);
  831. else
  832. StdEditorDialog := MessageBox (sUnknownDialog, nil, mfError + mfOkButton);
  833. end;
  834. end;
  835. {****************************************************************************
  836. Helpers
  837. ****************************************************************************}
  838. function CountLines(var Buf; Count: sw_Word): sw_Integer;
  839. var
  840. p : pchar;
  841. lines : sw_word;
  842. begin
  843. p:=pchar(@buf);
  844. lines:=0;
  845. while (count>0) do
  846. begin
  847. if p^ in [#10,#13] then
  848. begin
  849. inc(lines);
  850. if ord((p+1)^)+ord(p^)=23 then
  851. begin
  852. inc(p);
  853. dec(count);
  854. if count=0 then
  855. break;
  856. end;
  857. end;
  858. inc(p);
  859. dec(count);
  860. end;
  861. CountLines:=Lines;
  862. end;
  863. procedure GetLimits(var Buf; Count: sw_Word;var lim:objects.TPoint);
  864. { Get the limits needed for Buf, its an extended version of countlines (lim.y),
  865. which also gets the maximum line length in lim.x }
  866. var
  867. p : pchar;
  868. len : sw_word;
  869. begin
  870. lim.x:=0;
  871. lim.y:=0;
  872. len:=0;
  873. p:=pchar(@buf);
  874. while (count>0) do
  875. begin
  876. if p^ in [#10,#13] then
  877. begin
  878. if len>lim.x then
  879. lim.x:=len;
  880. inc(lim.y);
  881. if ord((p+1)^)+ord(p^)=23 then
  882. begin
  883. inc(p);
  884. dec(count);
  885. end;
  886. len:=0;
  887. end
  888. else
  889. inc(len);
  890. inc(p);
  891. dec(count);
  892. end;
  893. end;
  894. function ScanKeyMap(KeyMap: Pointer; KeyCode: Word): Word;
  895. var
  896. p : pword;
  897. count : sw_word;
  898. begin
  899. p:=keymap;
  900. count:=p^;
  901. inc(p);
  902. while (count>0) do
  903. begin
  904. if (lo(p^)=lo(keycode)) and
  905. ((hi(p^)=0) or (hi(p^)=hi(keycode))) then
  906. begin
  907. inc(p);
  908. scankeymap:=p^;
  909. exit;
  910. end;
  911. inc(p,2);
  912. dec(count);
  913. end;
  914. scankeymap:=0;
  915. end;
  916. Type
  917. Btable = Array[0..255] of Byte;
  918. Procedure BMMakeTable(const s:string; Var t : Btable);
  919. { Makes a Boyer-Moore search table. s = the search String t = the table }
  920. Var
  921. x : sw_integer;
  922. begin
  923. FillChar(t,sizeof(t),length(s));
  924. For x := length(s) downto 1 do
  925. if (t[ord(s[x])] = length(s)) then
  926. t[ord(s[x])] := length(s) - x;
  927. end;
  928. function Scan(var Block; Size: Sw_Word;const Str: String): Sw_Word;
  929. Var
  930. buffer : Array[0..MaxBufLength-1] of Byte Absolute block;
  931. s2 : String;
  932. len,
  933. numb : Sw_Word;
  934. found : Boolean;
  935. bt : Btable;
  936. begin
  937. BMMakeTable(str,bt);
  938. len:=length(str);
  939. s2[0]:=chr(len); { sets the length to that of the search String }
  940. found:=False;
  941. numb:=pred(len);
  942. While (not found) and (numb<(size-len)) do
  943. begin
  944. { partial match }
  945. if buffer[numb] = ord(str[len]) then
  946. begin
  947. { less partial! }
  948. if buffer[numb-pred(len)] = ord(str[1]) then
  949. begin
  950. move(buffer[numb-pred(len)],s2[1],len);
  951. if (str=s2) then
  952. begin
  953. found:=true;
  954. break;
  955. end;
  956. end;
  957. inc(numb);
  958. end
  959. else
  960. inc(numb,Bt[buffer[numb]]);
  961. end;
  962. if not found then
  963. Scan := NotFoundValue
  964. else
  965. Scan := numb - pred(len);
  966. end;
  967. function IScan(var Block; Size: Sw_Word;const Str: String): Sw_Word;
  968. Var
  969. buffer : Array[0..MaxBufLength-1] of Char Absolute block;
  970. s : String;
  971. len,
  972. numb,
  973. x : Sw_Word;
  974. found : Boolean;
  975. bt : Btable;
  976. p : pchar;
  977. c : char;
  978. begin
  979. len:=length(str);
  980. if (len=0) or (len>size) then
  981. begin
  982. IScan := NotFoundValue;
  983. exit;
  984. end;
  985. { create uppercased string }
  986. s[0]:=chr(len);
  987. for x:=1 to len do
  988. begin
  989. if str[x] in ['a'..'z'] then
  990. s[x]:=chr(ord(str[x])-32)
  991. else
  992. s[x]:=str[x];
  993. end;
  994. BMMakeTable(s,bt);
  995. found:=False;
  996. numb:=pred(len);
  997. While (not found) and (numb<(size-len)) do
  998. begin
  999. { partial match }
  1000. c:=buffer[numb];
  1001. if c in ['a'..'z'] then
  1002. c:=chr(ord(c)-32);
  1003. if (c=s[len]) then
  1004. begin
  1005. { less partial! }
  1006. p:=@buffer[numb-pred(len)];
  1007. x:=1;
  1008. while (x<=len) do
  1009. begin
  1010. if not(((p^ in ['a'..'z']) and (chr(ord(p^)-32)=s[x])) or
  1011. (p^=s[x])) then
  1012. break;
  1013. inc(p);
  1014. inc(x);
  1015. end;
  1016. if (x>len) then
  1017. begin
  1018. found:=true;
  1019. break;
  1020. end;
  1021. inc(numb);
  1022. end
  1023. else
  1024. inc(numb,Bt[ord(c)]);
  1025. end;
  1026. if not found then
  1027. IScan := NotFoundValue
  1028. else
  1029. IScan := numb - pred(len);
  1030. end;
  1031. {****************************************************************************
  1032. TIndicator
  1033. ****************************************************************************}
  1034. constructor TIndicator.Init (var Bounds : TRect);
  1035. begin
  1036. Inherited Init (Bounds);
  1037. GrowMode := gfGrowLoY + gfGrowHiY;
  1038. end; { TIndicator.Init }
  1039. procedure TIndicator.Draw;
  1040. VAR
  1041. Color : Byte;
  1042. Frame : Char;
  1043. L : array[0..1] of Longint;
  1044. S : String[15];
  1045. B : TDrawBuffer;
  1046. begin
  1047. if State and sfDragging = 0 then
  1048. begin
  1049. Color := GetColor (1);
  1050. Frame := #205;
  1051. end
  1052. else
  1053. begin
  1054. Color := GetColor (2);
  1055. Frame := #196;
  1056. end;
  1057. MoveChar (B, Frame, Color, Size.X);
  1058. { If the text has been modified, put an 'M' in the TIndicator display. }
  1059. if Modified then
  1060. WordRec (B[1]).Lo := 77;
  1061. { If WordWrap is active put a 'W' in the TIndicator display. }
  1062. if WordWrap then
  1063. WordRec (B[2]).Lo := 87
  1064. else
  1065. WordRec (B[2]).Lo := Byte (Frame);
  1066. { If AutoIndent is active put an 'I' in TIndicator display. }
  1067. if AutoIndent then
  1068. WordRec (B[0]).Lo := 73
  1069. else
  1070. WordRec (B[0]).Lo := Byte (Frame);
  1071. L[0] := Location.Y + 1;
  1072. L[1] := Location.X + 1;
  1073. FormatStr (S, ' %d:%d ', L);
  1074. MoveStr (B[9 - Pos (':', S)], S, Color); { Changed original 8 to 9. }
  1075. WriteBuf (0, 0, Size.X, 1, B);
  1076. end; { TIndicator.Draw }
  1077. function TIndicator.GetPalette : PPalette;
  1078. const
  1079. P : string[Length (CIndicator)] = CIndicator;
  1080. begin
  1081. GetPalette := PPalette(@P);
  1082. end; { TIndicator.GetPalette }
  1083. procedure TIndicator.SetState (AState : Word; Enable : Boolean);
  1084. begin
  1085. Inherited SetState (AState, Enable);
  1086. if AState = sfDragging then
  1087. DrawView;
  1088. end; { TIndicator.SetState }
  1089. procedure TIndicator.SetValue (ALocation : Objects.TPoint; IsAutoIndent : Boolean;
  1090. IsModified : Boolean;
  1091. IsWordWrap : Boolean);
  1092. begin
  1093. if (Location.X<>ALocation.X) or
  1094. (Location.Y<>ALocation.Y) or
  1095. (AutoIndent <> IsAutoIndent) or
  1096. (Modified <> IsModified) or
  1097. (WordWrap <> IsWordWrap) then
  1098. begin
  1099. Location := ALocation;
  1100. AutoIndent := IsAutoIndent; { Added provisions to show AutoIndent. }
  1101. Modified := IsModified;
  1102. WordWrap := IsWordWrap; { Added provisions to show WordWrap. }
  1103. DrawView;
  1104. end;
  1105. end; { TIndicator.SetValue }
  1106. {****************************************************************************
  1107. TLineInfo
  1108. ****************************************************************************}
  1109. constructor TLineInfo.Init;
  1110. begin
  1111. MaxPos:=0;
  1112. Grow(1);
  1113. end;
  1114. destructor TLineInfo.Done;
  1115. begin
  1116. FreeMem(Info,MaxPos*sizeof(TLineInfoRec));
  1117. Info := nil;
  1118. end;
  1119. procedure TLineInfo.Grow(pos:Sw_word);
  1120. var
  1121. NewSize : Sw_word;
  1122. P : pointer;
  1123. begin
  1124. NewSize:=(Pos+LineInfoGrow-(Pos mod LineInfoGrow));
  1125. GetMem(P,NewSize*sizeof(TLineInfoRec));
  1126. FillChar(P^,NewSize*sizeof(TLineInfoRec),0);
  1127. Move(Info^,P^,MaxPos*sizeof(TLineInfoRec));
  1128. Freemem(Info,MaxPos*sizeof(TLineInfoRec));
  1129. Info:=P;
  1130. end;
  1131. procedure TLineInfo.SetLen(pos,val:Sw_Word);
  1132. begin
  1133. if pos>=MaxPos then
  1134. Grow(Pos);
  1135. Info^[Pos].Len:=val
  1136. end;
  1137. procedure TLineInfo.SetAttr(pos,val:Sw_Word);
  1138. begin
  1139. if pos>=MaxPos then
  1140. Grow(Pos);
  1141. Info^[Pos].Attr:=val
  1142. end;
  1143. function TLineInfo.GetLen(pos:Sw_Word):Sw_Word;
  1144. begin
  1145. GetLen:=Info^[Pos].Len;
  1146. end;
  1147. function TLineInfo.GetAttr(pos:Sw_Word):Sw_Word;
  1148. begin
  1149. GetAttr:=Info^[Pos].Attr;
  1150. end;
  1151. {****************************************************************************
  1152. TEditor
  1153. ****************************************************************************}
  1154. constructor TEditor.Init (var Bounds : TRect;
  1155. AHScrollBar, AVScrollBar : PScrollBar;
  1156. AIndicator : PIndicator; ABufSize : Sw_Word);
  1157. var
  1158. Element : Byte; { Place_Marker array element to initialize array with. }
  1159. begin
  1160. Inherited Init (Bounds);
  1161. GrowMode := gfGrowHiX + gfGrowHiY;
  1162. Options := Options or ofSelectable;
  1163. Flags := EditorFlags;
  1164. EventMask := evMouseDown + evKeyDown + evCommand + evBroadcast;
  1165. ShowCursor;
  1166. HScrollBar := AHScrollBar;
  1167. VScrollBar := AVScrollBar;
  1168. Indicator := AIndicator;
  1169. BufSize := ABufSize;
  1170. CanUndo := True;
  1171. InitBuffer;
  1172. if assigned(Buffer) then
  1173. IsValid := True
  1174. else
  1175. begin
  1176. EditorDialog (edOutOfMemory, nil);
  1177. BufSize := 0;
  1178. end;
  1179. SetBufLen (0);
  1180. for Element := 1 to 10 do
  1181. Place_Marker[Element] := 0;
  1182. Element := 1;
  1183. while Element <= 70 do
  1184. begin
  1185. if Element mod 5 = 0 then
  1186. Insert ('x', Tab_Settings, Element)
  1187. else
  1188. Insert (#32, Tab_Settings, Element);
  1189. Inc (Element);
  1190. end;
  1191. { Default Right_Margin value. Change it if you want another. }
  1192. Right_Margin := 76;
  1193. TabSize:=8;
  1194. end; { TEditor.Init }
  1195. constructor TEditor.Load (var S : Objects.TStream);
  1196. begin
  1197. Inherited Load (S);
  1198. GetPeerViewPtr (S, HScrollBar);
  1199. GetPeerViewPtr (S, VScrollBar);
  1200. GetPeerViewPtr (S, Indicator);
  1201. S.Read (BufSize, SizeOf (BufSize));
  1202. S.Read (CanUndo, SizeOf (CanUndo));
  1203. S.Read (AutoIndent, SizeOf (AutoIndent));
  1204. S.Read (Line_Number, SizeOf (Line_Number));
  1205. S.Read (Place_Marker, SizeOf (Place_Marker));
  1206. S.Read (Right_Margin, SizeOf (Right_Margin));
  1207. S.Read (Tab_Settings, SizeOf (Tab_Settings));
  1208. S.Read (Word_Wrap, SizeOf (Word_Wrap));
  1209. InitBuffer;
  1210. if Assigned(Buffer) then
  1211. IsValid := True
  1212. else
  1213. begin
  1214. EditorDialog (edOutOfMemory, nil);
  1215. BufSize := 0;
  1216. end;
  1217. Lock;
  1218. SetBufLen (0);
  1219. end; { TEditor.Load }
  1220. destructor TEditor.Done;
  1221. begin
  1222. DoneBuffer;
  1223. Inherited Done;
  1224. end; { TEditor.Done }
  1225. function TEditor.BufChar(P: Sw_Word): Char;
  1226. begin
  1227. if P>=CurPtr then
  1228. inc(P,Gaplen);
  1229. BufChar:=Buffer^[P];
  1230. end;
  1231. function TEditor.BufPtr(P: Sw_Word): Sw_Word;
  1232. begin
  1233. if P>=CurPtr then
  1234. BufPtr:=P+GapLen
  1235. else
  1236. BufPtr:=P;
  1237. end;
  1238. procedure TEditor.Center_Text (Select_Mode : Byte);
  1239. { This procedure will center the current line of text. }
  1240. { Centering is based on the current Right_Margin. }
  1241. { If the Line_Length exceeds the Right_Margin, or the }
  1242. { line is just a blank line, we exit and do nothing. }
  1243. VAR
  1244. Spaces : array [1..80] of Char; { Array to hold spaces we'll insert. }
  1245. Index : Byte; { Index into Spaces array. }
  1246. Line_Length : Sw_Integer; { Holds the length of the line. }
  1247. E,S : Sw_Word; { End of the current line. }
  1248. begin
  1249. E := LineEnd (CurPtr);
  1250. S := LineStart (CurPtr);
  1251. { If the line is blank (only a CR/LF on it) then do noting. }
  1252. if E = S then
  1253. Exit;
  1254. { Set CurPtr to start of line. Check if line begins with a space. }
  1255. { We must strip out any spaces from the beginning, or end of lines. }
  1256. { If line does not start with space, make sure line length does not }
  1257. { exceed the Right_Margin. If it does, then do nothing. }
  1258. SetCurPtr (S, Select_Mode);
  1259. Remove_EOL_Spaces (Select_Mode);
  1260. if Buffer^[CurPtr] = #32 then
  1261. begin
  1262. { If the next word is greater than the end of line then do nothing. }
  1263. { If the line length is greater than Right_Margin then do nothing. }
  1264. { Otherwise, delete all spaces at the start of line. }
  1265. { Then reset end of line and put CurPtr at start of modified line. }
  1266. E := LineEnd (CurPtr);
  1267. if NextWord (CurPtr) > E then
  1268. Exit;
  1269. if E - NextWord (CurPtr) > Right_Margin then
  1270. Exit;
  1271. DeleteRange (CurPtr, NextWord (CurPtr), True);
  1272. E := LineEnd (CurPtr);
  1273. SetCurPtr (LineStart (CurPtr), Select_Mode);
  1274. end
  1275. else
  1276. if E - CurPtr > Right_Margin then
  1277. Exit;
  1278. { Now we determine the real length of the line. }
  1279. { Then we subtract the Line_Length from Right_Margin. }
  1280. { Dividing the result by two tells us how many spaces }
  1281. { must be inserted at start of line to center it. }
  1282. { When we're all done, set the CurPtr to end of line. }
  1283. Line_Length := E - CurPtr;
  1284. for Index := 1 to ((Right_Margin - Line_Length) shr 1) do
  1285. Spaces[Index] := #32;
  1286. InsertText (@Spaces, Index, False);
  1287. SetCurPtr (LineEnd (CurPtr), Select_Mode);
  1288. end; { TEditor.Center_Text }
  1289. procedure TEditor.ChangeBounds (var Bounds : TRect);
  1290. begin
  1291. SetBounds (Bounds);
  1292. Delta.X := Max (0, Min (Delta.X, Limit.X - Size.X));
  1293. Delta.Y := Max (0, Min (Delta.Y, Limit.Y - Size.Y));
  1294. Update (ufView);
  1295. end; { TEditor.ChangeBounds }
  1296. function TEditor.CharPos (P, Target : Sw_Word) : Sw_Integer;
  1297. VAR
  1298. Pos : Sw_Integer;
  1299. begin
  1300. Pos := 0;
  1301. while P < Target do
  1302. begin
  1303. if BufChar (P) = #9 then
  1304. Pos := Pos or 7;
  1305. Inc (Pos);
  1306. Inc (P);
  1307. end;
  1308. CharPos := Pos;
  1309. end; { TEditor.CharPos }
  1310. function TEditor.CharPtr (P : Sw_Word; Target : Sw_Integer) : Sw_Word;
  1311. VAR
  1312. Pos : Sw_Integer;
  1313. begin
  1314. Pos := 0;
  1315. while (Pos < Target) and (P < BufLen) and not(BufChar (P) in [#10,#13]) do
  1316. begin
  1317. if BufChar (P) = #9 then
  1318. Pos := Pos or 7;
  1319. Inc (Pos);
  1320. Inc (P);
  1321. end;
  1322. if Pos > Target then
  1323. Dec (P);
  1324. CharPtr := P;
  1325. end; { TEditor.CharPtr }
  1326. procedure TEditor.Check_For_Word_Wrap (Select_Mode : Byte;
  1327. Center_Cursor : Boolean);
  1328. { This procedure checks if CurPos.X > Right_Margin. }
  1329. { If it is, then we Do_Word_Wrap. Simple, eh? }
  1330. begin
  1331. if CurPos.X > Right_Margin then
  1332. Do_Word_Wrap (Select_Mode, Center_Cursor);
  1333. end; {Check_For_Word_Wrap}
  1334. function TEditor.ClipCopy : Boolean;
  1335. begin
  1336. ClipCopy := False;
  1337. if Assigned(Clipboard) and (Clipboard <> @Self) then
  1338. begin
  1339. ClipCopy := Clipboard^.InsertFrom (@Self);
  1340. Selecting := False;
  1341. Update (ufUpdate);
  1342. end;
  1343. end; { TEditor.ClipCopy }
  1344. procedure TEditor.ClipCut;
  1345. begin
  1346. if ClipCopy then
  1347. begin
  1348. Update_Place_Markers (0,
  1349. Self.SelEnd - Self.SelStart,
  1350. Self.SelStart,
  1351. Self.SelEnd);
  1352. DeleteSelect;
  1353. end;
  1354. end; { TEditor.ClipCut }
  1355. procedure TEditor.ClipPaste;
  1356. begin
  1357. if Assigned(Clipboard) and (Clipboard <> @Self) then
  1358. begin
  1359. { Do not allow paste operations that will exceed }
  1360. { the Right_Margin when Word_Wrap is active and }
  1361. { cursor is at EOL. }
  1362. if Word_Wrap and (CurPos.X > Right_Margin) then
  1363. begin
  1364. EditorDialog (edPasteNotPossible, nil);
  1365. Exit;
  1366. end;
  1367. { The editor will not copy selected text if the CurPtr }
  1368. { is not the same value as the SelStart. However, it }
  1369. { does return an InsCount. This may, or may not, be a }
  1370. { bug. We don't want to update the Place_Marker if }
  1371. { there's no text copied. }
  1372. if CurPtr = SelStart then
  1373. Update_Place_Markers (Clipboard^.SelEnd - Clipboard^.SelStart,
  1374. 0,
  1375. Clipboard^.SelStart,
  1376. Clipboard^.SelEnd);
  1377. InsertFrom (Clipboard);
  1378. end;
  1379. end; { TEditor.ClipPaste }
  1380. procedure TEditor.ConvertEvent (var Event : Drivers.TEvent);
  1381. VAR
  1382. ShiftState : Byte;
  1383. Key : Word;
  1384. begin
  1385. ShiftState:=GetShiftState;
  1386. if Event.What = evKeyDown then
  1387. begin
  1388. if (ShiftState and $03 <> 0)
  1389. and (Event.ScanCode >= $47)
  1390. and (Event.ScanCode <= $51) then
  1391. Event.CharCode := #0;
  1392. Key := Event.KeyCode;
  1393. if KeyState <> 0 then
  1394. begin
  1395. if (Lo (Key) >= $01) and (Lo (Key) <= $1A) then
  1396. Inc (Key, $40);
  1397. if (Lo (Key) >= $61) and (Lo (Key) <= $7A) then
  1398. Dec (Key, $20);
  1399. end;
  1400. Key := ScanKeyMap (KeyMap[KeyState], Key);
  1401. KeyState := 0;
  1402. if Key <> 0 then
  1403. if Hi (Key) = $FF then
  1404. begin
  1405. KeyState := Lo (Key);
  1406. ClearEvent (Event);
  1407. end
  1408. else
  1409. begin
  1410. Event.What := evCommand;
  1411. Event.Command := Key;
  1412. end;
  1413. end;
  1414. end; { TEditor.ConvertEvent }
  1415. function TEditor.CursorVisible : Boolean;
  1416. begin
  1417. CursorVisible := (CurPos.Y >= Delta.Y) and (CurPos.Y < Delta.Y + Size.Y);
  1418. end; { TEditor.CursorVisible }
  1419. procedure TEditor.DeleteRange (StartPtr, EndPtr : Sw_Word; DelSelect : Boolean);
  1420. begin
  1421. { This will update Place_Marker for all deletions. }
  1422. { EXCEPT the Remove_EOL_Spaces deletion. }
  1423. Update_Place_Markers (0, EndPtr - StartPtr, StartPtr, EndPtr);
  1424. if HasSelection and DelSelect then
  1425. DeleteSelect
  1426. else
  1427. begin
  1428. SetSelect (CurPtr, EndPtr, True);
  1429. DeleteSelect;
  1430. SetSelect (StartPtr, CurPtr, False);
  1431. DeleteSelect;
  1432. end;
  1433. end; { TEditor.DeleteRange }
  1434. procedure TEditor.DeleteSelect;
  1435. begin
  1436. InsertText (nil, 0, False);
  1437. end; { TEditor.DeleteSelect }
  1438. procedure TEditor.DoneBuffer;
  1439. begin
  1440. ReAllocMem(Buffer, 0);
  1441. end; { TEditor.DoneBuffer }
  1442. procedure TEditor.DoSearchReplace;
  1443. VAR
  1444. I : Sw_Word;
  1445. C : Objects.TPoint;
  1446. begin
  1447. repeat
  1448. I := cmCancel;
  1449. if not Search (FindStr, Flags) then
  1450. begin
  1451. if Flags and (efReplaceAll + efDoReplace) <> (efReplaceAll + efDoReplace) then
  1452. EditorDialog (edSearchFailed, nil)
  1453. end
  1454. else
  1455. if Flags and efDoReplace <> 0 then
  1456. begin
  1457. I := cmYes;
  1458. if Flags and efPromptOnReplace <> 0 then
  1459. begin
  1460. MakeGlobal (Cursor, C);
  1461. I := EditorDialog (edReplacePrompt, Pointer(@C));
  1462. end;
  1463. if I = cmYes then
  1464. begin
  1465. { If Word_Wrap is active and we are at EOL }
  1466. { disallow replace by bringing up a dialog }
  1467. { stating that replace is not possible. }
  1468. if Word_Wrap and
  1469. ((CurPos.X + (Length (ReplaceStr) - Length (FindStr))) > Right_Margin) then
  1470. EditorDialog (edReplaceNotPossible, nil)
  1471. else
  1472. begin
  1473. Lock;
  1474. Search_Replace := True;
  1475. if length (ReplaceStr) < length (FindStr) then
  1476. Update_Place_Markers (0,
  1477. Length (FindStr) - Length (ReplaceStr),
  1478. CurPtr - Length (FindStr) + Length (ReplaceStr),
  1479. CurPtr)
  1480. else
  1481. if length (ReplaceStr) > length (FindStr) then
  1482. Update_Place_Markers (Length (ReplaceStr) - Length (FindStr),
  1483. 0,
  1484. CurPtr,
  1485. CurPtr + (Length (ReplaceStr) - Length (FindStr)));
  1486. InsertText (@ReplaceStr[1], Length (ReplaceStr), False);
  1487. Search_Replace := False;
  1488. TrackCursor (False);
  1489. Unlock;
  1490. end;
  1491. end;
  1492. end;
  1493. until (I = cmCancel) or (Flags and efReplaceAll = 0);
  1494. end; { TEditor.DoSearchReplace }
  1495. procedure TEditor.DoUpdate;
  1496. begin
  1497. if UpdateFlags <> 0 then
  1498. begin
  1499. SetCursor (CurPos.X - Delta.X, CurPos.Y - Delta.Y);
  1500. if UpdateFlags and ufView <> 0 then
  1501. DrawView
  1502. else
  1503. if UpdateFlags and ufLine <> 0 then
  1504. DrawLines (CurPos.Y - Delta.Y, 1, LineStart (CurPtr));
  1505. if assigned(HScrollBar) then
  1506. HScrollBar^.SetParams (Delta.X, 0, Limit.X - Size.X, Size.X div 2, 1);
  1507. if assigned(VScrollBar) then
  1508. VScrollBar^.SetParams (Delta.Y, 0, Limit.Y - Size.Y, Size.Y - 1, 1);
  1509. if assigned(Indicator) then
  1510. Indicator^.SetValue (CurPos, AutoIndent, Modified, Word_Wrap);
  1511. if State and sfActive <> 0 then
  1512. UpdateCommands;
  1513. UpdateFlags := 0;
  1514. end;
  1515. end; { TEditor.DoUpdate }
  1516. function TEditor.Do_Word_Wrap (Select_Mode : Byte;
  1517. Center_Cursor : Boolean) : Boolean;
  1518. { This procedure does the actual wordwrap. It always assumes the CurPtr }
  1519. { is at Right_Margin + 1. It makes several tests for special conditions }
  1520. { and processes those first. If they all fail, it does a normal wrap. }
  1521. VAR
  1522. A : Sw_Word; { Distance between line start and first word on line. }
  1523. C : Sw_Word; { Current pointer when we come into procedure. }
  1524. L : Sw_Word; { BufLen when we come into procedure. }
  1525. P : Sw_Word; { Position of pointer at any given moment. }
  1526. S : Sw_Word; { Start of a line. }
  1527. begin
  1528. Do_Word_Wrap := False;
  1529. Select_Mode := 0;
  1530. if BufLen >= (BufSize - 1) then
  1531. exit;
  1532. C := CurPtr;
  1533. L := BufLen;
  1534. S := LineStart (CurPtr);
  1535. { If first character in the line is a space and autoindent mode is on }
  1536. { then we check to see if NextWord(S) exceeds the CurPtr. If it does, }
  1537. { we set CurPtr as the AutoIndent marker. If it doesn't, we will set }
  1538. { NextWord(S) as the AutoIndent marker. If neither, we set it to S. }
  1539. if AutoIndent and (Buffer^[S] = ' ') then
  1540. begin
  1541. if NextWord (S) > CurPtr then
  1542. A := CurPtr
  1543. else
  1544. A := NextWord (S);
  1545. end
  1546. else
  1547. A := NextWord (S);
  1548. { Though NewLine will remove EOL spaces, we do it here too. }
  1549. { This catches the instance where a user may try to space }
  1550. { completely across the line, in which case CurPtr.X = 0. }
  1551. Remove_EOL_Spaces (Select_Mode);
  1552. if CurPos.X = 0 then
  1553. begin
  1554. NewLine (Select_Mode);
  1555. Do_Word_Wrap := True;
  1556. Exit;
  1557. end;
  1558. { At this point we have one of five situations: }
  1559. { }
  1560. { 1) AutoIndent is on and this line is all spaces before CurPtr. }
  1561. { 2) AutoIndent is off and this line is all spaces before CurPtr. }
  1562. { 3) AutoIndent is on and this line is continuous characters before CurPtr. }
  1563. { 4) AutoIndent is off and this line is continuous characters before CurPtr. }
  1564. { 5) This is just a normal line of text. }
  1565. { }
  1566. { Conditions 1 through 4 have to be taken into account before condition 5. }
  1567. { First, we see if there are all spaces and/or all characters. }
  1568. { Then we determine which one it really is. Finally, we take }
  1569. { a course of action based on the state of AutoIndent. }
  1570. if PrevWord (CurPtr) <= S then
  1571. begin
  1572. P := CurPtr - 1;
  1573. while ((Buffer^[P] <> ' ') and (P > S)) do
  1574. Dec (P);
  1575. { We found NO SPACES. Conditions 4 and 5 are treated the same. }
  1576. { We can NOT do word wrap and put up a dialog box stating such. }
  1577. { Delete character just entered so we don't exceed Right_Margin. }
  1578. if P = S then
  1579. begin
  1580. EditorDialog (edWrapNotPossible, nil);
  1581. DeleteRange (PrevChar (CurPtr), CurPtr, True);
  1582. Exit;
  1583. end
  1584. else
  1585. begin
  1586. { There are spaces. Now find out if they are all spaces. }
  1587. { If so, see if AutoIndent is on. If it is, turn it off, }
  1588. { do a NewLine, and turn it back on. Otherwise, just do }
  1589. { the NewLine. We go through all of these gyrations for }
  1590. { AutoIndent. Being way out here with a preceding line }
  1591. { of spaces and wrapping with AutoIndent on is real dumb! }
  1592. { However, the user expects something. The wrap will NOT }
  1593. { autoindent, but they had no business being here anyway! }
  1594. P := CurPtr - 1;
  1595. while ((Buffer^[P] = ' ') and (P > S)) do
  1596. Dec (P);
  1597. if P = S then
  1598. begin
  1599. if Autoindent then
  1600. begin
  1601. AutoIndent := False;
  1602. NewLine (Select_Mode);
  1603. AutoIndent := True;
  1604. end
  1605. else
  1606. NewLine (Select_Mode);
  1607. end; { AutoIndent }
  1608. end; { P = S for spaces }
  1609. end { P = S for no spaces }
  1610. else { PrevWord (CurPtr) <= S }
  1611. begin
  1612. { Hooray! We actually had a plain old line of text to wrap! }
  1613. { Regardless if we are pushing out a line beyond the Right_Margin, }
  1614. { or at the end of a line itself, the following will determine }
  1615. { exactly where to do the wrap and re-set the cursor accordingly. }
  1616. { However, if P = A then we can't wrap. Show dialog and exit. }
  1617. P := CurPtr;
  1618. while P - S > Right_Margin do
  1619. P := PrevWord (P);
  1620. if (P = A) then
  1621. begin
  1622. EditorDialog (edReformNotPossible, nil);
  1623. SetCurPtr (P, Select_Mode);
  1624. Exit;
  1625. end;
  1626. SetCurPtr (P, Select_Mode);
  1627. NewLine (Select_Mode);
  1628. end; { PrevWord (CurPtr <= S }
  1629. { Track the cursor here (it is at CurPos.X = 0) so the view }
  1630. { will redraw itself at column 0. This eliminates having it }
  1631. { redraw starting at the current cursor and not being able }
  1632. { to see text before the cursor. Of course, we also end up }
  1633. { redrawing the view twice, here and back in HandleEvent. }
  1634. { }
  1635. { Reposition cursor so user can pick up where they left off. }
  1636. TrackCursor (Center_Cursor);
  1637. SetCurPtr (C - (L - BufLen), Select_Mode);
  1638. Do_Word_Wrap := True;
  1639. end; { TEditor.Do_Word_Wrap }
  1640. procedure TEditor.Draw;
  1641. begin
  1642. if DrawLine <> Delta.Y then
  1643. begin
  1644. DrawPtr := LineMove (DrawPtr, Delta.Y - DrawLine);
  1645. DrawLine := Delta.Y;
  1646. end;
  1647. DrawLines (0, Size.Y, DrawPtr);
  1648. end; { TEditor.Draw }
  1649. procedure TEditor.DrawLines (Y, Count : Sw_Integer; LinePtr : Sw_Word);
  1650. VAR
  1651. Color : Word;
  1652. B : array[0..MaxLineLength - 1] of Sw_Word;
  1653. begin
  1654. Color := GetColor ($0201);
  1655. while Count > 0 do
  1656. begin
  1657. FormatLine (B, LinePtr, Delta.X + Size.X, Color);
  1658. WriteBuf (0, Y, Size.X, 1, B[Delta.X]);
  1659. LinePtr := NextLine (LinePtr);
  1660. Inc (Y);
  1661. Dec (Count);
  1662. end;
  1663. end; { TEditor.DrawLines }
  1664. procedure TEditor.Find;
  1665. VAR
  1666. FindRec : TFindDialogRec;
  1667. begin
  1668. with FindRec do
  1669. begin
  1670. Find := FindStr;
  1671. Options := Flags;
  1672. if EditorDialog (edFind, @FindRec) <> cmCancel then
  1673. begin
  1674. FindStr := Find;
  1675. Flags := Options and not efDoReplace;
  1676. DoSearchReplace;
  1677. end;
  1678. end;
  1679. end; { TEditor.Find }
  1680. procedure TEditor.FormatLine (var DrawBuf; LinePtr : Sw_Word;
  1681. Width : Sw_Integer;
  1682. Colors : Word);
  1683. var
  1684. outptr : pword;
  1685. outcnt,
  1686. idxpos : Sw_Word;
  1687. attr : Word;
  1688. procedure FillSpace(i:Sw_Word);
  1689. var
  1690. w : word;
  1691. begin
  1692. inc(OutCnt,i);
  1693. w:=32 or attr;
  1694. while (i>0) do
  1695. begin
  1696. OutPtr^:=w;
  1697. inc(OutPtr);
  1698. dec(i);
  1699. end;
  1700. end;
  1701. function FormatUntil(endpos:Sw_word):boolean;
  1702. var
  1703. p : pchar;
  1704. begin
  1705. FormatUntil:=false;
  1706. p:=pchar(Buffer)+idxpos;
  1707. while endpos>idxpos do
  1708. begin
  1709. if OutCnt>=Width then
  1710. exit;
  1711. case p^ of
  1712. #9 :
  1713. FillSpace(Tabsize-(outcnt mod Tabsize));
  1714. #10,#13 :
  1715. begin
  1716. FillSpace(Width-OutCnt);
  1717. FormatUntil:=true;
  1718. exit;
  1719. end;
  1720. else
  1721. begin
  1722. inc(OutCnt);
  1723. OutPtr^:=ord(p^) or attr;
  1724. inc(OutPtr);
  1725. end;
  1726. end; { case }
  1727. inc(p);
  1728. inc(idxpos);
  1729. end;
  1730. end;
  1731. begin
  1732. OutCnt:=0;
  1733. OutPtr:=@DrawBuf;
  1734. idxPos:=LinePtr;
  1735. attr:=lo(Colors) shl 8;
  1736. if FormatUntil(SelStart) then
  1737. exit;
  1738. attr:=hi(Colors) shl 8;
  1739. if FormatUntil(CurPtr) then
  1740. exit;
  1741. inc(idxPos,GapLen);
  1742. if FormatUntil(SelEnd+GapLen) then
  1743. exit;
  1744. attr:=lo(Colors) shl 8;
  1745. if FormatUntil(BufSize) then
  1746. exit;
  1747. { fill up until width }
  1748. FillSpace(Width-OutCnt);
  1749. end; {TEditor.FormatLine}
  1750. function TEditor.GetMousePtr (Mouse : Objects.TPoint) : Sw_Word;
  1751. begin
  1752. MakeLocal (Mouse, Mouse);
  1753. Mouse.X := Max (0, Min (Mouse.X, Size.X - 1));
  1754. Mouse.Y := Max (0, Min (Mouse.Y, Size.Y - 1));
  1755. GetMousePtr := CharPtr (LineMove (DrawPtr, Mouse.Y + Delta.Y - DrawLine),
  1756. Mouse.X + Delta.X);
  1757. end; { TEditor.GetMousePtr }
  1758. function TEditor.GetPalette : PPalette;
  1759. CONST
  1760. P : String[Length (CEditor)] = CEditor;
  1761. begin
  1762. GetPalette := PPalette(@P);
  1763. end; { TEditor.GetPalette }
  1764. procedure TEditor.HandleEvent (var Event : Drivers.TEvent);
  1765. VAR
  1766. ShiftState : Byte;
  1767. CenterCursor : Boolean;
  1768. SelectMode : Byte;
  1769. D : Objects.TPoint;
  1770. Mouse : Objects.TPoint;
  1771. function CheckScrollBar (P : PScrollBar; var D : Sw_Integer) : Boolean;
  1772. begin
  1773. CheckScrollBar := FALSE;
  1774. if (Event.InfoPtr = P) and (P^.Value <> D) then
  1775. begin
  1776. D := P^.Value;
  1777. Update (ufView);
  1778. CheckScrollBar := TRUE;
  1779. end;
  1780. end; {CheckScrollBar}
  1781. begin
  1782. Inherited HandleEvent (Event);
  1783. ConvertEvent (Event);
  1784. CenterCursor := not CursorVisible;
  1785. SelectMode := 0;
  1786. ShiftState:=GetShiftState;
  1787. if Selecting or (ShiftState and $03 <> 0) then
  1788. SelectMode := smExtend;
  1789. case Event.What of
  1790. Drivers.evMouseDown:
  1791. begin
  1792. if Event.Double then
  1793. SelectMode := SelectMode or smDouble;
  1794. repeat
  1795. Lock;
  1796. if Event.What = evMouseAuto then
  1797. begin
  1798. MakeLocal (Event.Where, Mouse);
  1799. D := Delta;
  1800. if Mouse.X < 0 then
  1801. Dec (D.X);
  1802. if Mouse.X >= Size.X then
  1803. Inc (D.X);
  1804. if Mouse.Y < 0 then
  1805. Dec (D.Y);
  1806. if Mouse.Y >= Size.Y then
  1807. Inc (D.Y);
  1808. ScrollTo (D.X, D.Y);
  1809. end;
  1810. SetCurPtr (GetMousePtr (Event.Where), SelectMode);
  1811. SelectMode := SelectMode or smExtend;
  1812. Unlock;
  1813. until not MouseEvent (Event, evMouseMove + evMouseAuto);
  1814. end; { Drivers.evMouseDown }
  1815. Drivers.evKeyDown:
  1816. case Event.CharCode of
  1817. #32..#255:
  1818. begin
  1819. Lock;
  1820. if Overwrite and not HasSelection then
  1821. if CurPtr <> LineEnd (CurPtr) then
  1822. SelEnd := NextChar (CurPtr);
  1823. InsertText (@Event.CharCode, 1, False);
  1824. if Word_Wrap then
  1825. Check_For_Word_Wrap (SelectMode, CenterCursor);
  1826. TrackCursor (CenterCursor);
  1827. Unlock;
  1828. end;
  1829. else
  1830. Exit;
  1831. end; { Drivers.evKeyDown }
  1832. Drivers.evCommand:
  1833. case Event.Command of
  1834. cmFind : Find;
  1835. cmReplace : Replace;
  1836. cmSearchAgain : DoSearchReplace;
  1837. else
  1838. begin
  1839. Lock;
  1840. case Event.Command of
  1841. cmCut : ClipCut;
  1842. cmCopy : ClipCopy;
  1843. cmPaste : ClipPaste;
  1844. cmUndo : Undo;
  1845. cmClear : DeleteSelect;
  1846. cmCharLeft : SetCurPtr (PrevChar (CurPtr), SelectMode);
  1847. cmCharRight : SetCurPtr (NextChar (CurPtr), SelectMode);
  1848. cmWordLeft : SetCurPtr (PrevWord (CurPtr), SelectMode);
  1849. cmWordRight : SetCurPtr (NextWord (CurPtr), SelectMode);
  1850. cmLineStart : SetCurPtr (LineStart (CurPtr), SelectMode);
  1851. cmLineEnd : SetCurPtr (LineEnd (CurPtr), SelectMode);
  1852. cmLineUp : SetCurPtr (LineMove (CurPtr, -1), SelectMode);
  1853. cmLineDown : SetCurPtr (LineMove (CurPtr, 1), SelectMode);
  1854. cmPageUp : SetCurPtr (LineMove (CurPtr, - (Size.Y - 1)), SelectMode);
  1855. cmPageDown : SetCurPtr (LineMove (CurPtr, Size.Y - 1), SelectMode);
  1856. cmTextStart : SetCurPtr (0, SelectMode);
  1857. cmTextEnd : SetCurPtr (BufLen, SelectMode);
  1858. cmNewLine : NewLine (SelectMode);
  1859. cmBackSpace : DeleteRange (PrevChar (CurPtr), CurPtr, True);
  1860. cmDelChar : DeleteRange (CurPtr, NextChar (CurPtr), True);
  1861. cmDelWord : DeleteRange (CurPtr, NextWord (CurPtr), False);
  1862. cmDelStart : DeleteRange (LineStart (CurPtr), CurPtr, False);
  1863. cmDelEnd : DeleteRange (CurPtr, LineEnd (CurPtr), False);
  1864. cmDelLine : DeleteRange (LineStart (CurPtr), NextLine (CurPtr), False);
  1865. cmInsMode : ToggleInsMode;
  1866. cmStartSelect : StartSelect;
  1867. cmHideSelect : HideSelect;
  1868. cmIndentMode : begin
  1869. AutoIndent := not AutoIndent;
  1870. Update (ufStats);
  1871. end; { Added provision to update TIndicator if ^QI pressed. }
  1872. cmCenterText : Center_Text (SelectMode);
  1873. cmEndPage : SetCurPtr (LineMove (CurPtr, Delta.Y - CurPos.Y + Size.Y - 1), SelectMode);
  1874. cmHomePage : SetCurPtr (LineMove (CurPtr, -(CurPos.Y - Delta.Y)), SelectMode);
  1875. cmInsertLine : Insert_Line (SelectMode);
  1876. cmJumpLine : Jump_To_Line (SelectMode);
  1877. cmReformDoc : Reformat_Document (SelectMode, CenterCursor);
  1878. cmReformPara : Reformat_Paragraph (SelectMode, CenterCursor);
  1879. cmRightMargin : Set_Right_Margin;
  1880. cmScrollDown : Scroll_Down;
  1881. cmScrollUp : Scroll_Up;
  1882. cmSelectWord : Select_Word;
  1883. cmSetTabs : Set_Tabs;
  1884. cmTabKey : Tab_Key (SelectMode);
  1885. cmWordWrap : begin
  1886. Word_Wrap := not Word_Wrap;
  1887. Update (ufStats);
  1888. end; { Added provision to update TIndicator if ^OW pressed. }
  1889. cmSetMark0 : Set_Place_Marker (10);
  1890. cmSetMark1 : Set_Place_Marker (1);
  1891. cmSetMark2 : Set_Place_Marker (2);
  1892. cmSetMark3 : Set_Place_Marker (3);
  1893. cmSetMark4 : Set_Place_Marker (4);
  1894. cmSetMark5 : Set_Place_Marker (5);
  1895. cmSetMark6 : Set_Place_Marker (6);
  1896. cmSetMark7 : Set_Place_Marker (7);
  1897. cmSetMark8 : Set_Place_Marker (8);
  1898. cmSetMark9 : Set_Place_Marker (9);
  1899. cmJumpMark0 : Jump_Place_Marker (10, SelectMode);
  1900. cmJumpMark1 : Jump_Place_Marker (1, SelectMode);
  1901. cmJumpMark2 : Jump_Place_Marker (2, SelectMode);
  1902. cmJumpMark3 : Jump_Place_Marker (3, SelectMode);
  1903. cmJumpMark4 : Jump_Place_Marker (4, SelectMode);
  1904. cmJumpMark5 : Jump_Place_Marker (5, SelectMode);
  1905. cmJumpMark6 : Jump_Place_Marker (6, SelectMode);
  1906. cmJumpMark7 : Jump_Place_Marker (7, SelectMode);
  1907. cmJumpMark8 : Jump_Place_Marker (8, SelectMode);
  1908. cmJumpMark9 : Jump_Place_Marker (9, SelectMode);
  1909. else
  1910. Unlock;
  1911. Exit;
  1912. end; { Event.Command (Inner) }
  1913. TrackCursor (CenterCursor);
  1914. { If the user presses any key except cmNewline or cmBackspace }
  1915. { we need to check if the file has been modified yet. There }
  1916. { can be no spaces at the end of a line, or wordwrap doesn't }
  1917. { work properly. We don't want to do this if the file hasn't }
  1918. { been modified because the user could be bringing in an ASCII }
  1919. { file from an editor that allows spaces at the EOL. If we }
  1920. { took them out in that scenario the "M" would appear on the }
  1921. { TIndicator line and the user would get upset or confused. }
  1922. if (Event.Command <> cmNewLine) and
  1923. (Event.Command <> cmBackSpace) and
  1924. (Event.Command <> cmTabKey) and
  1925. Modified then
  1926. Remove_EOL_Spaces (SelectMode);
  1927. Unlock;
  1928. end; { Event.Command (Outer) }
  1929. end; { Drivers.evCommand }
  1930. Drivers.evBroadcast:
  1931. case Event.Command of
  1932. cmScrollBarChanged:
  1933. if (Event.InfoPtr = HScrollBar) or
  1934. (Event.InfoPtr = VScrollBar) then
  1935. begin
  1936. CheckScrollBar (HScrollBar, Delta.X);
  1937. CheckScrollBar (VScrollBar, Delta.Y);
  1938. end
  1939. else
  1940. exit;
  1941. else
  1942. Exit;
  1943. end; { Drivers.evBroadcast }
  1944. end;
  1945. ClearEvent (Event);
  1946. end; { TEditor.HandleEvent }
  1947. function TEditor.HasSelection : Boolean;
  1948. begin
  1949. HasSelection := SelStart <> SelEnd;
  1950. end; { TEditor.HasSelection }
  1951. procedure TEditor.HideSelect;
  1952. begin
  1953. Selecting := False;
  1954. SetSelect (CurPtr, CurPtr, False);
  1955. end; { TEditor.HideSelect }
  1956. procedure TEditor.InitBuffer;
  1957. begin
  1958. Assert(Buffer = nil, 'TEditor.InitBuffer: Buffer is not nil');
  1959. ReAllocMem(Buffer, BufSize);
  1960. end; { TEditor.InitBuffer }
  1961. function TEditor.InsertBuffer (var P : PEditBuffer;
  1962. Offset, Length : Sw_Word;
  1963. AllowUndo, SelectText : Boolean) : Boolean;
  1964. VAR
  1965. SelLen : Sw_Word;
  1966. DelLen : Sw_Word;
  1967. SelLines : Sw_Word;
  1968. Lines : Sw_Word;
  1969. NewSize : Longint;
  1970. begin
  1971. InsertBuffer := True;
  1972. Selecting := False;
  1973. SelLen := SelEnd - SelStart;
  1974. if (SelLen = 0) and (Length = 0) then
  1975. Exit;
  1976. DelLen := 0;
  1977. if AllowUndo then
  1978. if CurPtr = SelStart then
  1979. DelLen := SelLen
  1980. else
  1981. if SelLen > InsCount then
  1982. DelLen := SelLen - InsCount;
  1983. NewSize := Longint (BufLen + DelCount - SelLen + DelLen) + Length;
  1984. if NewSize > BufLen + DelCount then
  1985. if (NewSize > MaxBufLength) or not SetBufSize (NewSize) then
  1986. begin
  1987. EditorDialog (edOutOfMemory, nil);
  1988. InsertBuffer := False;
  1989. SelEnd := SelStart;
  1990. Exit;
  1991. end;
  1992. SelLines := CountLines (Buffer^[BufPtr (SelStart)], SelLen);
  1993. if CurPtr = SelEnd then
  1994. begin
  1995. if AllowUndo then
  1996. begin
  1997. if DelLen > 0 then
  1998. Move (Buffer^[SelStart], Buffer^[CurPtr + GapLen - DelCount - DelLen], DelLen);
  1999. Dec (InsCount, SelLen - DelLen);
  2000. end;
  2001. CurPtr := SelStart;
  2002. Dec (CurPos.Y, SelLines);
  2003. end;
  2004. if Delta.Y > CurPos.Y then
  2005. begin
  2006. Dec (Delta.Y, SelLines);
  2007. if Delta.Y < CurPos.Y then
  2008. Delta.Y := CurPos.Y;
  2009. end;
  2010. if Length > 0 then
  2011. Move (P^[Offset], Buffer^[CurPtr], Length);
  2012. Lines := CountLines (Buffer^[CurPtr], Length);
  2013. Inc (CurPtr, Length);
  2014. Inc (CurPos.Y, Lines);
  2015. DrawLine := CurPos.Y;
  2016. DrawPtr := LineStart (CurPtr);
  2017. CurPos.X := CharPos (DrawPtr, CurPtr);
  2018. if not SelectText then
  2019. SelStart := CurPtr;
  2020. SelEnd := CurPtr;
  2021. if Length>Sellen then
  2022. begin
  2023. Inc (BufLen, Length - SelLen);
  2024. Dec (GapLen, Length - SelLen);
  2025. end
  2026. else
  2027. begin
  2028. Dec (BufLen, Sellen - Length);
  2029. Inc (GapLen, Sellen - Length);
  2030. end;
  2031. if AllowUndo then
  2032. begin
  2033. Inc (DelCount, DelLen);
  2034. Inc (InsCount, Length);
  2035. end;
  2036. Inc (Limit.Y, Lines - SelLines);
  2037. Delta.Y := Max (0, Min (Delta.Y, Limit.Y - Size.Y));
  2038. if not IsClipboard then
  2039. Modified := True;
  2040. SetBufSize (BufLen + DelCount);
  2041. if (SelLines = 0) and (Lines = 0) then
  2042. Update (ufLine)
  2043. else
  2044. Update (ufView);
  2045. end; { TEditor.InsertBuffer }
  2046. function TEditor.InsertFrom (Editor : PEditor) : Boolean;
  2047. begin
  2048. InsertFrom := InsertBuffer (Editor^.Buffer,
  2049. Editor^.BufPtr (Editor^.SelStart),
  2050. Editor^.SelEnd - Editor^.SelStart, CanUndo, IsClipboard);
  2051. end; { TEditor.InsertFrom }
  2052. procedure TEditor.Insert_Line (Select_Mode : Byte);
  2053. { This procedure inserts a newline at the current cursor position }
  2054. { if a ^N is pressed. Unlike cmNewLine, the cursor will return }
  2055. { to its original position. If the cursor was at the end of a }
  2056. { line, and its spaces were removed, the cursor returns to the }
  2057. { end of the line instead. }
  2058. begin
  2059. NewLine (Select_Mode);
  2060. SetCurPtr (LineEnd (LineMove (CurPtr, -1)), Select_Mode);
  2061. end; { TEditor.Insert_Line }
  2062. function TEditor.InsertText (Text : Pointer;
  2063. Length : Sw_Word;
  2064. SelectText : Boolean) : Boolean;
  2065. begin
  2066. if assigned(Text) and not Search_Replace then
  2067. Update_Place_Markers (Length, 0, Self.SelStart, Self.SelEnd);
  2068. InsertText := InsertBuffer (PEditBuffer (Text),
  2069. 0, Length, CanUndo, SelectText);
  2070. end; { TEditor.InsertText }
  2071. function TEditor.IsClipboard : Boolean;
  2072. begin
  2073. IsClipboard := Clipboard = @Self;
  2074. end; { TEditor.IsClipboard }
  2075. procedure TEditor.Jump_Place_Marker (Element : Byte; Select_Mode : Byte);
  2076. { This procedure jumps to a place marker if ^Q# is pressed. }
  2077. { We don't go anywhere if Place_Marker[Element] is not zero. }
  2078. begin
  2079. if (not IsClipboard) and (Place_Marker[Element] <> 0) then
  2080. SetCurPtr (Place_Marker[Element], Select_Mode);
  2081. end; { TEditor.Jump_Place_Marker }
  2082. procedure TEditor.Jump_To_Line (Select_Mode : Byte);
  2083. { This function brings up a dialog box that allows }
  2084. { the user to select a line number to jump to. }
  2085. VAR
  2086. Code : Integer; { Used for Val conversion. }
  2087. Temp_Value : Longint; { Holds converted dialog value. }
  2088. begin
  2089. if EditorDialog (edJumpToLine, @Line_Number) <> cmCancel then
  2090. begin
  2091. { Convert the Line_Number string to an interger. }
  2092. { Put it into Temp_Value. If the number is not }
  2093. { in the range 1..9999 abort. If the number is }
  2094. { our current Y position, abort. Otherwise, }
  2095. { go to top of document, and jump to the line. }
  2096. { There are faster methods. This one's easy. }
  2097. { Note that CurPos.Y is always 1 less than what }
  2098. { the TIndicator line says. }
  2099. val (Line_Number, Temp_Value, Code);
  2100. if (Temp_Value < 1) or (Temp_Value > 9999999) then
  2101. Exit;
  2102. if Temp_Value = CurPos.Y + 1 then
  2103. Exit;
  2104. SetCurPtr (0, Select_Mode);
  2105. SetCurPtr (LineMove (CurPtr, Temp_Value - 1), Select_Mode);
  2106. end;
  2107. end; {TEditor.Jump_To_Line}
  2108. function TEditor.LineEnd (P : Sw_Word) : Sw_Word;
  2109. var
  2110. start,
  2111. i : Sw_word;
  2112. pc : pchar;
  2113. begin
  2114. if P<CurPtr then
  2115. begin
  2116. i:=CurPtr-P;
  2117. pc:=pchar(Buffer)+P;
  2118. while (i>0) do
  2119. begin
  2120. if pc^ in [#10,#13] then
  2121. begin
  2122. LineEnd:=pc-pchar(Buffer);
  2123. exit;
  2124. end;
  2125. inc(pc);
  2126. dec(i);
  2127. end;
  2128. start:=CurPtr;
  2129. end
  2130. else
  2131. start:=P;
  2132. i:=BufLen-Start;
  2133. pc:=pchar(Buffer)+GapLen+start;
  2134. while (i>0) do
  2135. begin
  2136. if pc^ in [#10,#13] then
  2137. begin
  2138. LineEnd:=pc-(pchar(Buffer)+Gaplen);
  2139. exit;
  2140. end;
  2141. inc(pc);
  2142. dec(i);
  2143. end;
  2144. LineEnd:=pc-(pchar(Buffer)+Gaplen);
  2145. end; { TEditor.LineEnd }
  2146. function TEditor.LineMove (P : Sw_Word; Count : Sw_Integer) : Sw_Word;
  2147. VAR
  2148. Pos : Sw_Integer;
  2149. I : Sw_Word;
  2150. begin
  2151. I := P;
  2152. P := LineStart (P);
  2153. Pos := CharPos (P, I);
  2154. while Count <> 0 do
  2155. begin
  2156. I := P;
  2157. if Count < 0 then
  2158. begin
  2159. P := PrevLine (P);
  2160. Inc (Count);
  2161. end
  2162. else
  2163. begin
  2164. P := NextLine (P);
  2165. Dec (Count);
  2166. end;
  2167. end;
  2168. if P <> I then
  2169. P := CharPtr (P, Pos);
  2170. LineMove := P;
  2171. end; { TEditor.LineMove }
  2172. function TEditor.LineStart (P : Sw_Word) : Sw_Word;
  2173. var
  2174. i : Sw_word;
  2175. start,pc : pchar;
  2176. oc : char;
  2177. begin
  2178. if P>CurPtr then
  2179. begin
  2180. start:=pchar(Buffer)+GapLen;
  2181. pc:=start;
  2182. i:=P-CurPtr;
  2183. dec(pc);
  2184. while (i>0) do
  2185. begin
  2186. if pc^ in [#10,#13] then
  2187. break;
  2188. dec(pc);
  2189. dec(i);
  2190. end;
  2191. end
  2192. else
  2193. i:=0;
  2194. if i=0 then
  2195. begin
  2196. start:=pchar(Buffer);
  2197. i:=P;
  2198. pc:=start+p;
  2199. dec(pc);
  2200. while (i>0) do
  2201. begin
  2202. if pc^ in [#10,#13] then
  2203. break;
  2204. dec(pc);
  2205. dec(i);
  2206. end;
  2207. if i=0 then
  2208. begin
  2209. LineStart:=0;
  2210. exit;
  2211. end;
  2212. end;
  2213. oc:=pc^;
  2214. LineStart:=pc-start+1;
  2215. end; { TEditor.LineStart }
  2216. function TEditor.LineNr (P : Sw_Word) : Sw_Word;
  2217. var
  2218. pc,endp : pchar;
  2219. lines : sw_word;
  2220. begin
  2221. endp:=pchar(Buffer)+BufPtr(P);
  2222. pc:=pchar(Buffer);
  2223. lines:=0;
  2224. while (pc<endp) do
  2225. begin
  2226. if pc^ in [#10,#13] then
  2227. begin
  2228. inc(lines);
  2229. if ord((pc+1)^)+ord(pc^)=23 then
  2230. begin
  2231. inc(pc);
  2232. if (pc>=endp) then
  2233. break;
  2234. end;
  2235. end;
  2236. inc(pc);
  2237. end;
  2238. LineNr:=Lines;
  2239. end;
  2240. procedure TEditor.Lock;
  2241. begin
  2242. Inc (LockCount);
  2243. end; { TEditor.Lock }
  2244. function TEditor.NewLine (Select_Mode : Byte) : Boolean;
  2245. VAR
  2246. I : Sw_Word; { Used to track spaces for AutoIndent. }
  2247. P : Sw_Word; { Position of Cursor when we arrive and after Newline. }
  2248. begin
  2249. P := LineStart (CurPtr);
  2250. I := P;
  2251. { The first thing we do is remove any End Of Line spaces. }
  2252. { Then we check to see how many spaces are on beginning }
  2253. { of a line. We need this check to add them after CR/LF }
  2254. { if AutoIndenting. Last of all we insert spaces required }
  2255. { for the AutoIndenting, if it was on. }
  2256. Remove_EOL_Spaces (Select_Mode);
  2257. while (I < CurPtr) and ((Buffer^[I] in [#9,' '])) do
  2258. Inc (I);
  2259. if InsertText (@LineBreak[1], length(LineBreak), False) = FALSE then
  2260. exit;
  2261. if AutoIndent then
  2262. InsertText (@Buffer^[P], I - P, False);
  2263. { Remember where the CurPtr is at this moment. }
  2264. { Remember the length of the buffer at the moment. }
  2265. { Go to the previous line and remove EOL spaces. }
  2266. { Once removed, re-set the cursor to where we were }
  2267. { minus any spaces that might have been removed. }
  2268. I := BufLen;
  2269. P := CurPtr;
  2270. SetCurPtr (LineMove (CurPtr, - 1), Select_Mode);
  2271. Remove_EOL_Spaces (Select_Mode);
  2272. if I - BufLen <> 0 then
  2273. SetCurPtr (P - (I - BufLen), Select_Mode)
  2274. else
  2275. SetCurPtr (P, Select_Mode);
  2276. NewLine:=true;
  2277. end; { TEditor.NewLine }
  2278. function TEditor.NextChar (P : Sw_Word) : Sw_Word;
  2279. var
  2280. pc : pchar;
  2281. begin
  2282. if P<>BufLen then
  2283. begin
  2284. inc(P);
  2285. if P<>BufLen then
  2286. begin
  2287. pc:=pchar(Buffer);
  2288. if P>=CurPtr then
  2289. inc(pc,GapLen);
  2290. inc(pc,P-1);
  2291. if ord(pc^)+ord((pc+1)^)=23 then
  2292. inc(p);
  2293. end;
  2294. end;
  2295. NextChar:=P;
  2296. end; { TEditor.NextChar }
  2297. function TEditor.NextLine (P : Sw_Word) : Sw_Word;
  2298. begin
  2299. NextLine := NextChar (LineEnd (P));
  2300. end; { TEditor.NextLine }
  2301. function TEditor.NextWord (P : Sw_Word) : Sw_Word;
  2302. begin
  2303. { skip word }
  2304. while (P < BufLen) and (BufChar (P) in WordChars) do
  2305. P := NextChar (P);
  2306. { skip spaces }
  2307. while (P < BufLen) and not (BufChar (P) in WordChars) do
  2308. P := NextChar (P);
  2309. NextWord := P;
  2310. end; { TEditor.NextWord }
  2311. function TEditor.PrevChar (P : Sw_Word) : Sw_Word;
  2312. var
  2313. pc : pchar;
  2314. begin
  2315. if p<>0 then
  2316. begin
  2317. dec(p);
  2318. if p<>0 then
  2319. begin
  2320. pc:=pchar(Buffer);
  2321. if P>=CurPtr then
  2322. inc(pc,GapLen);
  2323. inc(pc,P-1);
  2324. if ord(pc^)+ord((pc+1)^)=23 then
  2325. dec(p);
  2326. end;
  2327. end;
  2328. PrevChar:=P;
  2329. end; { TEditor.PrevChar }
  2330. function TEditor.PrevLine (P : Sw_Word) : Sw_Word;
  2331. begin
  2332. PrevLine := LineStart (PrevChar (P));
  2333. end; { TEditor.PrevLine }
  2334. function TEditor.PrevWord (P : Sw_Word) : Sw_Word;
  2335. begin
  2336. { skip spaces }
  2337. while (P > 0) and not (BufChar (PrevChar (P)) in WordChars) do
  2338. P := PrevChar (P);
  2339. { skip word }
  2340. while (P > 0) and (BufChar (PrevChar (P)) in WordChars) do
  2341. P := PrevChar (P);
  2342. PrevWord := P;
  2343. end; { TEditor.PrevWord }
  2344. procedure TEditor.Reformat_Document (Select_Mode : Byte; Center_Cursor : Boolean);
  2345. { This procedure will do a reformat of the entire document, or just }
  2346. { from the current line to the end of the document, if ^QU is pressed. }
  2347. { It simply brings up the correct dialog box, and then calls the }
  2348. { TEditor.Reformat_Paragraph procedure to do the actual reformatting. }
  2349. CONST
  2350. efCurrentLine = $0000; { Radio button #1 selection for dialog box. }
  2351. efWholeDocument = $0001; { Radio button #2 selection for dialog box. }
  2352. VAR
  2353. Reformat_Options : Word; { Holds the dialog options for reformatting. }
  2354. begin
  2355. { Check if Word_Wrap is toggled on. If NOT on, check if programmer }
  2356. { allows reformatting of document and if not show user dialog that }
  2357. { says reformatting is not permissable. }
  2358. if not Word_Wrap then
  2359. begin
  2360. if not Allow_Reformat then
  2361. begin
  2362. EditorDialog (edReformatNotAllowed, nil);
  2363. Exit;
  2364. end;
  2365. Word_Wrap := True;
  2366. Update (ufStats);
  2367. end;
  2368. { Default radio button option to 1st one. Bring up dialog box. }
  2369. Reformat_Options := efCurrentLine;
  2370. if EditorDialog (edReformatDocument, @Reformat_Options) <> cmCancel then
  2371. begin
  2372. { If the option to reformat the whole document was selected }
  2373. { we need to go back to start of document. Otherwise we stay }
  2374. { on the current line. Call Reformat_Paragraph until we get }
  2375. { to the end of the document to do the reformatting. }
  2376. if Reformat_Options and efWholeDocument <> 0 then
  2377. SetCurPtr (0, Select_Mode);
  2378. Unlock;
  2379. repeat
  2380. Lock;
  2381. if NOT Reformat_Paragraph (Select_Mode, Center_Cursor) then
  2382. Exit;
  2383. TrackCursor (False);
  2384. Unlock;
  2385. until CurPtr = BufLen;
  2386. end;
  2387. end; { TEditor.Reformat_Document }
  2388. function TEditor.Reformat_Paragraph (Select_Mode : Byte;
  2389. Center_Cursor : Boolean) : Boolean;
  2390. { This procedure will do a reformat of the current paragraph if ^B pressed. }
  2391. { The feature works regardless if wordrap is on or off. It also supports }
  2392. { the AutoIndent feature. Reformat is not possible if the CurPos exceeds }
  2393. { the Right_Margin. Right_Margin is where the EOL is considered to be. }
  2394. CONST
  2395. Space : array [1..2] of Char = #32#32;
  2396. VAR
  2397. C : Sw_Word; { Position of CurPtr when we come into procedure. }
  2398. E : Sw_Word; { End of a line. }
  2399. S : Sw_Word; { Start of a line. }
  2400. begin
  2401. Reformat_Paragraph := False;
  2402. { Check if Word_Wrap is toggled on. If NOT on, check if programmer }
  2403. { allows reformatting of paragraph and if not show user dialog that }
  2404. { says reformatting is not permissable. }
  2405. if not Word_Wrap then
  2406. begin
  2407. if not Allow_Reformat then
  2408. begin
  2409. EditorDialog (edReformatNotAllowed, nil);
  2410. Exit;
  2411. end;
  2412. Word_Wrap := True;
  2413. Update (ufStats);
  2414. end;
  2415. C := CurPtr;
  2416. E := LineEnd (CurPtr);
  2417. S := LineStart (CurPtr);
  2418. { Reformat possible only if current line is NOT blank! }
  2419. if E <> S then
  2420. begin
  2421. { Reformat is NOT possible if the first word }
  2422. { on the line is beyond the Right_Margin. }
  2423. S := LineStart (CurPtr);
  2424. if NextWord (S) - S >= Right_Margin - 1 then
  2425. begin
  2426. EditorDialog (edReformNotPossible, nil);
  2427. Exit;
  2428. end;
  2429. { First objective is to find the first blank line }
  2430. { after this paragraph so we know when to stop. }
  2431. { That could be the end of the document. }
  2432. Repeat
  2433. SetCurPtr (LineMove (CurPtr, 1), Select_Mode);
  2434. E := LineEnd (CurPtr);
  2435. S := LineStart (CurPtr);
  2436. BlankLine := E;
  2437. until ((CurPtr = BufLen) or (E = S));
  2438. SetCurPtr (C, Select_Mode);
  2439. repeat
  2440. { Set CurPtr to LineEnd and remove the EOL spaces. }
  2441. { Pull up the next line and remove its EOL space. }
  2442. { First make sure the next line is not BlankLine! }
  2443. { Insert spaces as required between the two lines. }
  2444. SetCurPtr (LineEnd (CurPtr), Select_Mode);
  2445. Remove_EOL_Spaces (Select_Mode);
  2446. if CurPtr <> Blankline - 2 then
  2447. DeleteRange (CurPtr, Nextword (CurPtr), True);
  2448. Remove_EOL_Spaces (Select_Mode);
  2449. case Buffer^[CurPtr-1] of
  2450. '!' : InsertText (@Space, 2, False);
  2451. '.' : InsertText (@Space, 2, False);
  2452. ':' : InsertText (@Space, 2, False);
  2453. '?' : InsertText (@Space, 2, False);
  2454. else
  2455. InsertText (@Space, 1, False);
  2456. end;
  2457. { Reset CurPtr to EOL. While line length is > Right_Margin }
  2458. { go Do_Word_Wrap. If wordrap failed, exit routine. }
  2459. SetCurPtr (LineEnd (CurPtr), Select_Mode);
  2460. while LineEnd (CurPtr) - LineStart (CurPtr) > Right_Margin do
  2461. if not Do_Word_Wrap (Select_Mode, Center_Cursor) then
  2462. Exit;
  2463. { If LineEnd - LineStart > Right_Margin then set CurPtr }
  2464. { to Right_Margin on current line. Otherwise we set the }
  2465. { CurPtr to LineEnd. This gyration sets up the conditions }
  2466. { to test for time of loop exit. }
  2467. if LineEnd (CurPtr) - LineStart (CurPtr) > Right_Margin then
  2468. SetCurPtr (LineStart (CurPtr) + Right_Margin, Select_Mode)
  2469. else
  2470. SetCurPtr (LineEnd (CurPtr), Select_Mode);
  2471. until ((CurPtr >= BufLen) or (CurPtr >= BlankLine - 2));
  2472. end;
  2473. { If not at the end of the document reset CurPtr to start of next line. }
  2474. { This should be a blank line between paragraphs. }
  2475. if CurPtr < BufLen then
  2476. SetCurPtr (LineMove (CurPtr, 1), Select_Mode);
  2477. Reformat_Paragraph := True;
  2478. end; { TEditor.Reformat_Paragraph }
  2479. procedure TEditor.Remove_EOL_Spaces (Select_Mode : Byte);
  2480. { This procedure tests to see if there are consecutive spaces }
  2481. { at the end of a line (EOL). If so, we delete all spaces }
  2482. { after the last non-space character to the end of line. }
  2483. { We then reset the CurPtr to where we ended up at. }
  2484. VAR
  2485. C : Sw_Word; { Current pointer when we come into procedure. }
  2486. E : Sw_Word; { End of line. }
  2487. P : Sw_Word; { Position of pointer at any given moment. }
  2488. S : Sw_Word; { Start of a line. }
  2489. begin
  2490. C := CurPtr;
  2491. E := LineEnd (CurPtr);
  2492. P := E;
  2493. S := LineStart (CurPtr);
  2494. { Start at the end of a line and move towards the start. }
  2495. { Find first non-space character in that direction. }
  2496. while (P > S) and (BufChar (PrevChar (P)) = #32) do
  2497. P := PrevChar (P);
  2498. { If we found any spaces then delete them. }
  2499. if P < E then
  2500. begin
  2501. SetSelect (P, E, True);
  2502. DeleteSelect;
  2503. Update_Place_Markers (0, E - P, P, E);
  2504. end;
  2505. { If C, our pointer when we came into this procedure, }
  2506. { is less than the CurPtr then reset CurPtr to C so }
  2507. { cursor is where we started. Otherwise, set it to }
  2508. { the new CurPtr, for we have deleted characters. }
  2509. if C < CurPtr then
  2510. SetCurPtr (C, Select_Mode)
  2511. else
  2512. SetCurPtr (CurPtr, Select_Mode);
  2513. end; { TEditor.Remove_EOL_Spaces }
  2514. procedure TEditor.Replace;
  2515. VAR
  2516. ReplaceRec : TReplaceDialogRec;
  2517. begin
  2518. with ReplaceRec do
  2519. begin
  2520. Find := FindStr;
  2521. Replace := ReplaceStr;
  2522. Options := Flags;
  2523. if EditorDialog (edReplace, @ReplaceRec) <> cmCancel then
  2524. begin
  2525. FindStr := Find;
  2526. ReplaceStr := Replace;
  2527. Flags := Options or efDoReplace;
  2528. DoSearchReplace;
  2529. end;
  2530. end;
  2531. end; { TEditor.Replace }
  2532. procedure TEditor.Scroll_Down;
  2533. { This procedure will scroll the screen up, and always keep }
  2534. { the cursor on the CurPos.Y position, but not necessarily on }
  2535. { the CurPos.X. If CurPos.Y scrolls off the screen, the cursor }
  2536. { will stay in the upper left corner of the screen. This will }
  2537. { simulate the same process in the IDE. The CurPos.X coordinate }
  2538. { only messes up if we are on long lines and we then encounter }
  2539. { a shorter or blank line beneath the current one as we scroll. }
  2540. { In that case, it goes to the end of the new line. }
  2541. VAR
  2542. C : Sw_Word; { Position of CurPtr when we enter procedure. }
  2543. P : Sw_Word; { Position of CurPtr at any given time. }
  2544. W : Objects.TPoint; { CurPos.Y of CurPtr and P ('.X and '.Y). }
  2545. begin
  2546. { Remember current cursor position. Remember current CurPos.Y position. }
  2547. { Now issue the equivalent of a [Ctrl]-[End] command so the cursor will }
  2548. { go to the bottom of the current screen. Reset the cursor to this new }
  2549. { position and then send FALSE to TrackCursor so we fool it into }
  2550. { incrementing Delta.Y by only +1. If we didn't do this it would try }
  2551. { to center the cursor on the screen by fiddling with Delta.Y. }
  2552. C := CurPtr;
  2553. W.X := CurPos.Y;
  2554. P := LineMove (CurPtr, Delta.Y - CurPos.Y + Size.Y);
  2555. SetCurPtr (P, 0);
  2556. TrackCursor (False);
  2557. { Now remember where the new CurPos.Y is. See if distance between new }
  2558. { CurPos.Y and old CurPos.Y are greater than the current screen size. }
  2559. { If they are, we need to move cursor position itself down by one. }
  2560. { Otherwise, send the cursor back to our original CurPtr. }
  2561. W.Y := CurPos.Y;
  2562. if W.Y - W.X > Size.Y - 1 then
  2563. SetCurPtr (LineMove (C, 1), 0)
  2564. else
  2565. SetCurPtr (C, 0);
  2566. end; { TEditor.Scroll_Down }
  2567. procedure TEditor.Scroll_Up;
  2568. { This procedure will scroll the screen down, and always keep }
  2569. { the cursor on the CurPos.Y position, but not necessarily on }
  2570. { the CurPos.X. If CurPos.Y scrolls off the screen, the cursor }
  2571. { will stay in the bottom left corner of the screen. This will }
  2572. { simulate the same process in the IDE. The CurPos.X coordinate }
  2573. { only messes up if we are on long lines and we then encounter }
  2574. { a shorter or blank line beneath the current one as we scroll. }
  2575. { In that case, it goes to the end of the new line. }
  2576. VAR
  2577. C : Sw_Word; { Position of CurPtr when we enter procedure. }
  2578. P : Sw_Word; { Position of CurPtr at any given time. }
  2579. W : Objects.TPoint; { CurPos.Y of CurPtr and P ('.X and '.Y). }
  2580. begin
  2581. { Remember current cursor position. Remember current CurPos.Y position. }
  2582. { Now issue the equivalent of a [Ctrl]-[Home] command so the cursor will }
  2583. { go to the top of the current screen. Reset the cursor to this new }
  2584. { position and then send FALSE to TrackCursor so we fool it into }
  2585. { decrementing Delta.Y by only -1. If we didn't do this it would try }
  2586. { to center the cursor on the screen by fiddling with Delta.Y. }
  2587. C := CurPtr;
  2588. W.Y := CurPos.Y;
  2589. P := LineMove (CurPtr, -(CurPos.Y - Delta.Y + 1));
  2590. SetCurPtr (P, 0);
  2591. TrackCursor (False);
  2592. { Now remember where the new CurPos.Y is. See if distance between new }
  2593. { CurPos.Y and old CurPos.Y are greater than the current screen size. }
  2594. { If they are, we need to move the cursor position itself up by one. }
  2595. { Otherwise, send the cursor back to our original CurPtr. }
  2596. W.X := CurPos.Y;
  2597. if W.Y - W.X > Size.Y - 1 then
  2598. SetCurPtr (LineMove (C, -1), 0)
  2599. else
  2600. SetCurPtr (C, 0);
  2601. end; { TEditor.Scroll_Up }
  2602. procedure TEditor.ScrollTo (X, Y : Sw_Integer);
  2603. begin
  2604. X := Max (0, Min (X, Limit.X - Size.X));
  2605. Y := Max (0, Min (Y, Limit.Y - Size.Y));
  2606. if (X <> Delta.X) or (Y <> Delta.Y) then
  2607. begin
  2608. Delta.X := X;
  2609. Delta.Y := Y;
  2610. Update (ufView);
  2611. end;
  2612. end; { TEditor.ScrollTo }
  2613. function TEditor.Search (const FindStr : String; Opts : Word) : Boolean;
  2614. VAR
  2615. I,Pos : Sw_Word;
  2616. begin
  2617. Search := False;
  2618. Pos := CurPtr;
  2619. repeat
  2620. if Opts and efCaseSensitive <> 0 then
  2621. I := Scan (Buffer^[BufPtr (Pos)], BufLen - Pos, FindStr)
  2622. else
  2623. I := IScan (Buffer^[BufPtr (Pos)], BufLen - Pos, FindStr);
  2624. if (I <> sfSearchFailed) then
  2625. begin
  2626. Inc (I, Pos);
  2627. if (Opts and efWholeWordsOnly = 0) or
  2628. not (((I <> 0) and (BufChar (I - 1) in WordChars)) or
  2629. ((I + Length (FindStr) <> BufLen) and
  2630. (BufChar (I + Length (FindStr)) in WordChars))) then
  2631. begin
  2632. Lock;
  2633. SetSelect (I, I + Length (FindStr), False);
  2634. TrackCursor (not CursorVisible);
  2635. Unlock;
  2636. Search := True;
  2637. Exit;
  2638. end
  2639. else
  2640. Pos := I + 1;
  2641. end;
  2642. until I = sfSearchFailed;
  2643. end; { TEditor.Search }
  2644. procedure TEditor.Select_Word;
  2645. { This procedure will select the a word to put into the clipboard. }
  2646. { I've added it just to maintain compatibility with the IDE editor. }
  2647. { Note that selection starts at the current cursor position and ends }
  2648. { when a space or the end of line is encountered. }
  2649. VAR
  2650. E : Sw_Word; { End of the current line. }
  2651. Select_Mode : Byte; { Allows us to turn select mode on inside procedure. }
  2652. begin
  2653. E := LineEnd (CurPtr);
  2654. { If the cursor is on a space or at the end of a line, abort. }
  2655. { Stupid action on users part for you can't select blanks! }
  2656. if (BufChar (CurPtr) = #32) or (CurPtr = E) then
  2657. Exit;
  2658. { Turn on select mode and tell editor to start selecting text. }
  2659. { As long as we have a character > a space (this is done to }
  2660. { exclude CR/LF pairs at end of a line) and we are NOT at the }
  2661. { end of a line, set the CurPtr to the next character. }
  2662. { Once we find a space or CR/LF, selection is done and we }
  2663. { automatically put the selected word into the Clipboard. }
  2664. Select_Mode := smExtend;
  2665. StartSelect;
  2666. while (BufChar (NextChar (CurPtr)) > #32) and (CurPtr < E) do
  2667. SetCurPtr (NextChar (CurPtr), Select_Mode);
  2668. SetCurPtr (NextChar (CurPtr), Select_Mode);
  2669. ClipCopy;
  2670. end; {TEditor.Select_Word }
  2671. procedure TEditor.SetBufLen (Length : Sw_Word);
  2672. begin
  2673. BufLen := Length;
  2674. GapLen := BufSize - Length;
  2675. SelStart := 0;
  2676. SelEnd := 0;
  2677. CurPtr := 0;
  2678. CurPos.X:=0;
  2679. CurPos.Y:=0;
  2680. Delta.X:=0;
  2681. Delta.Y:=0;
  2682. GetLimits(Buffer^[GapLen], BufLen,Limit);
  2683. inc(Limit.X);
  2684. inc(Limit.Y);
  2685. DrawLine := 0;
  2686. DrawPtr := 0;
  2687. DelCount := 0;
  2688. InsCount := 0;
  2689. Modified := False;
  2690. Update (ufView);
  2691. end; { TEditor.SetBufLen }
  2692. function TEditor.SetBufSize (NewSize : Sw_Word) : Boolean;
  2693. begin
  2694. ReAllocMem(Buffer, NewSize);
  2695. BufSize := NewSize;
  2696. SetBufSize := True;
  2697. end; { TEditor.SetBufSize }
  2698. procedure TEditor.SetCmdState (Command : Word; Enable : Boolean);
  2699. VAR
  2700. S : TCommandSet;
  2701. begin
  2702. S := [Command];
  2703. if Enable and (State and sfActive <> 0) then
  2704. EnableCommands (S)
  2705. else
  2706. DisableCommands (S);
  2707. end; { TEditor.SetCmdState }
  2708. procedure TEditor.SetCurPtr (P : Sw_Word; SelectMode : Byte);
  2709. VAR
  2710. Anchor : Sw_Word;
  2711. begin
  2712. if SelectMode and smExtend = 0 then
  2713. Anchor := P
  2714. else
  2715. if CurPtr = SelStart then
  2716. Anchor := SelEnd
  2717. else
  2718. Anchor := SelStart;
  2719. if P < Anchor then
  2720. begin
  2721. if SelectMode and smDouble <> 0 then
  2722. begin
  2723. P := PrevLine (NextLine (P));
  2724. Anchor := NextLine (PrevLine (Anchor));
  2725. end;
  2726. SetSelect (P, Anchor, True);
  2727. end
  2728. else
  2729. begin
  2730. if SelectMode and smDouble <> 0 then
  2731. begin
  2732. P := NextLine (P);
  2733. Anchor := PrevLine (NextLine (Anchor));
  2734. end;
  2735. SetSelect (Anchor, P, False);
  2736. end;
  2737. end; { TEditor.SetCurPtr }
  2738. procedure TEditor.Set_Place_Marker (Element : Byte);
  2739. { This procedure sets a place marker for the CurPtr if ^K# is pressed. }
  2740. begin
  2741. if not IsClipboard then
  2742. Place_Marker[Element] := CurPtr;
  2743. end; { TEditor.Set_Place_Marker }
  2744. procedure TEditor.Set_Right_Margin;
  2745. { This procedure will bring up a dialog box }
  2746. { that allows the user to set Right_Margin. }
  2747. { Values must be < MaxLineLength and > 9. }
  2748. VAR
  2749. Code : Integer; { Used for Val conversion. }
  2750. Margin_Data : TRightMarginRec; { Holds dialog results. }
  2751. Temp_Value : Sw_Integer; { Holds converted dialog value. }
  2752. begin
  2753. with Margin_Data do
  2754. begin
  2755. Str (Right_Margin, Margin_Position);
  2756. if EditorDialog (edRightMargin, @Margin_Position) <> cmCancel then
  2757. begin
  2758. val (Margin_Position, Temp_Value, Code);
  2759. if (Temp_Value <= MaxLineLength) and (Temp_Value > 9) then
  2760. Right_Margin := Temp_Value;
  2761. end;
  2762. end;
  2763. end; { TEditor.Set_Right_Margin }
  2764. procedure TEditor.SetSelect (NewStart, NewEnd : Sw_Word; CurStart : Boolean);
  2765. VAR
  2766. UFlags : Byte;
  2767. P : Sw_Word;
  2768. L : Sw_Word;
  2769. begin
  2770. if CurStart then
  2771. P := NewStart
  2772. else
  2773. P := NewEnd;
  2774. UFlags := ufUpdate;
  2775. if (NewStart <> SelStart) or (NewEnd <> SelEnd) then
  2776. if (NewStart <> NewEnd) or (SelStart <> SelEnd) then
  2777. UFlags := ufView;
  2778. if P <> CurPtr then
  2779. begin
  2780. if P > CurPtr then
  2781. begin
  2782. L := P - CurPtr;
  2783. Move (Buffer^[CurPtr + GapLen], Buffer^[CurPtr], L);
  2784. Inc (CurPos.Y, CountLines (Buffer^[CurPtr], L));
  2785. CurPtr := P;
  2786. end
  2787. else
  2788. begin
  2789. L := CurPtr - P;
  2790. CurPtr := P;
  2791. Dec (CurPos.Y, CountLines (Buffer^[CurPtr], L));
  2792. Move (Buffer^[CurPtr], Buffer^[CurPtr + GapLen], L);
  2793. end;
  2794. DrawLine := CurPos.Y;
  2795. DrawPtr := LineStart (P);
  2796. CurPos.X := CharPos (DrawPtr, P);
  2797. DelCount := 0;
  2798. InsCount := 0;
  2799. SetBufSize (BufLen);
  2800. end;
  2801. SelStart := NewStart;
  2802. SelEnd := NewEnd;
  2803. Update (UFlags);
  2804. end; { TEditor.Select }
  2805. procedure TEditor.SetState (AState : Word; Enable : Boolean);
  2806. begin
  2807. Inherited SetState (AState, Enable);
  2808. case AState of
  2809. sfActive: begin
  2810. if assigned(HScrollBar) then
  2811. HScrollBar^.SetState (sfVisible, Enable);
  2812. if assigned(VScrollBar) then
  2813. VScrollBar^.SetState (sfVisible, Enable);
  2814. if assigned(Indicator) then
  2815. Indicator^.SetState (sfVisible, Enable);
  2816. UpdateCommands;
  2817. end;
  2818. sfExposed: if Enable then Unlock;
  2819. end;
  2820. end; { TEditor.SetState }
  2821. procedure TEditor.Set_Tabs;
  2822. { This procedure will bring up a dialog box }
  2823. { that allows the user to set tab stops. }
  2824. VAR
  2825. Index : Sw_Integer; { Index into string array. }
  2826. Tab_Data : TTabStopRec; { Holds dialog results. }
  2827. begin
  2828. with Tab_Data do
  2829. begin
  2830. { Assign current Tab_Settings to Tab_String. }
  2831. { Bring up the tab dialog so user can set tabs. }
  2832. Tab_String := Copy (Tab_Settings, 1, Tab_Stop_Length);
  2833. if EditorDialog (edSetTabStops, @Tab_String) <> cmCancel then
  2834. begin
  2835. { If Tab_String comes back as empty then set Tab_Settings to nil. }
  2836. { Otherwise, find the last character in Tab_String that is not }
  2837. { a space and copy Tab_String into Tab_Settings up to that spot. }
  2838. if Length (Tab_String) = 0 then
  2839. begin
  2840. FillChar (Tab_Settings, SizeOf (Tab_Settings), #0);
  2841. Tab_Settings[0] := #0;
  2842. Exit;
  2843. end
  2844. else
  2845. begin
  2846. Index := Length (Tab_String);
  2847. while Tab_String[Index] <= #32 do
  2848. Dec (Index);
  2849. Tab_Settings := Copy (Tab_String, 1, Index);
  2850. end;
  2851. end;
  2852. end;
  2853. end; { TEditor.Set_Tabs }
  2854. procedure TEditor.StartSelect;
  2855. begin
  2856. HideSelect;
  2857. Selecting := True;
  2858. end; { TEditor.StartSelect }
  2859. procedure TEditor.Store (var S : Objects.TStream);
  2860. begin
  2861. Inherited Store (S);
  2862. PutPeerViewPtr (S, HScrollBar);
  2863. PutPeerViewPtr (S, VScrollBar);
  2864. PutPeerViewPtr (S, Indicator);
  2865. S.Write (BufSize, SizeOf (BufSize));
  2866. S.Write (Canundo, SizeOf (Canundo));
  2867. S.Write (AutoIndent, SizeOf (AutoIndent));
  2868. S.Write (Line_Number, SizeOf (Line_Number));
  2869. S.Write (Place_Marker, SizeOf (Place_Marker));
  2870. S.Write (Right_Margin, SizeOf (Right_Margin));
  2871. S.Write (Tab_Settings, SizeOf (Tab_Settings));
  2872. S.Write (Word_Wrap, SizeOf (Word_Wrap));
  2873. end; { Editor.Store }
  2874. procedure TEditor.Tab_Key (Select_Mode : Byte);
  2875. { This function determines if we are in overstrike or insert mode, }
  2876. { and then moves the cursor if overstrike, or adds spaces if insert. }
  2877. VAR
  2878. E : Sw_Word; { End of current line. }
  2879. Index : Sw_Integer; { Loop counter. }
  2880. Position : Sw_Integer; { CurPos.X position. }
  2881. S : Sw_Word; { Start of current line. }
  2882. Spaces : array [1..80] of Char; { Array to hold spaces for insertion. }
  2883. begin
  2884. E := LineEnd (CurPtr);
  2885. S := LineStart (CurPtr);
  2886. { Find the current horizontal cursor position. }
  2887. { Now loop through the Tab_Settings string and }
  2888. { find the next available tab stop. }
  2889. Position := CurPos.X + 1;
  2890. repeat
  2891. Inc (Position);
  2892. until (Tab_Settings[Position] <> #32) or (Position >= Ord (Tab_Settings[0]));
  2893. E := CurPos.X;
  2894. Index := 1;
  2895. { Now we enter a loop to go to the next tab position. }
  2896. { If we are in overwrite mode, we just move the cursor }
  2897. { through the text to the next tab stop. If we are in }
  2898. { insert mode, we add spaces to the Spaces array for }
  2899. { the number of times we loop. }
  2900. while Index < Position - E do
  2901. begin
  2902. if Overwrite then
  2903. begin
  2904. if (Position > LineEnd (CurPtr) - LineStart (CurPtr))
  2905. or (Position > Ord (Tab_Settings[0])) then
  2906. begin
  2907. SetCurPtr (LineStart (LineMove (CurPtr, 1)), Select_Mode);
  2908. Exit;
  2909. end
  2910. else
  2911. if CurPtr < BufLen then
  2912. SetCurPtr (NextChar (CurPtr), Select_Mode);
  2913. end
  2914. else
  2915. begin
  2916. if (Position > Right_Margin) or (Position > Ord (Tab_Settings[0])) then
  2917. begin
  2918. SetCurPtr (LineStart (LineMove (CurPtr, 1)), Select_Mode);
  2919. Exit;
  2920. end
  2921. else
  2922. Spaces[Index] := #32;
  2923. end;
  2924. Inc (Index);
  2925. end;
  2926. { If we are insert mode, we insert spaces to the next tab stop. }
  2927. { When we're all done, the cursor will be sitting on the new tab stop. }
  2928. if not OverWrite then
  2929. InsertText (@Spaces, Index - 1, False);
  2930. end; { TEditor.Tab_Key }
  2931. procedure TEditor.ToggleInsMode;
  2932. begin
  2933. Overwrite := not Overwrite;
  2934. SetState (sfCursorIns, not GetState (sfCursorIns));
  2935. end; { TEditor.ToggleInsMode }
  2936. procedure TEditor.TrackCursor (Center : Boolean);
  2937. begin
  2938. if Center then
  2939. ScrollTo (CurPos.X - Size.X + 1, CurPos.Y - Size.Y div 2)
  2940. else
  2941. ScrollTo (Max (CurPos.X - Size.X + 1, Min (Delta.X, CurPos.X)),
  2942. Max (CurPos.Y - Size.Y + 1, Min (Delta.Y, CurPos.Y)));
  2943. end; { TEditor.TrackCursor }
  2944. procedure TEditor.Undo;
  2945. VAR
  2946. Length : Sw_Word;
  2947. begin
  2948. if (DelCount <> 0) or (InsCount <> 0) then
  2949. begin
  2950. Update_Place_Markers (DelCount, 0, CurPtr, CurPtr + DelCount);
  2951. SelStart := CurPtr - InsCount;
  2952. SelEnd := CurPtr;
  2953. Length := DelCount;
  2954. DelCount := 0;
  2955. InsCount := 0;
  2956. InsertBuffer (Buffer, CurPtr + GapLen - Length, Length, False, True);
  2957. end;
  2958. end; { TEditor.Undo }
  2959. procedure TEditor.Unlock;
  2960. begin
  2961. if LockCount > 0 then
  2962. begin
  2963. Dec (LockCount);
  2964. if LockCount = 0 then
  2965. DoUpdate;
  2966. end;
  2967. end; { TEditor.Unlock }
  2968. procedure TEditor.Update (AFlags : Byte);
  2969. begin
  2970. UpdateFlags := UpdateFlags or AFlags;
  2971. if LockCount = 0 then
  2972. DoUpdate;
  2973. end; { TEditor.Update }
  2974. procedure TEditor.UpdateCommands;
  2975. begin
  2976. SetCmdState (cmUndo, (DelCount <> 0) or (InsCount <> 0));
  2977. if not IsClipboard then
  2978. begin
  2979. SetCmdState (cmCut, HasSelection);
  2980. SetCmdState (cmCopy, HasSelection);
  2981. SetCmdState (cmPaste, assigned(Clipboard) and (Clipboard^.HasSelection));
  2982. end;
  2983. SetCmdState (cmClear, HasSelection);
  2984. SetCmdState (cmFind, True);
  2985. SetCmdState (cmReplace, True);
  2986. SetCmdState (cmSearchAgain, True);
  2987. end; { TEditor.UpdateCommands }
  2988. procedure TEditor.Update_Place_Markers (AddCount : Word; KillCount : Word;
  2989. StartPtr,EndPtr : Sw_Word);
  2990. { This procedure updates the position of the place markers }
  2991. { as the user inserts and deletes text in the document. }
  2992. VAR
  2993. Element : Byte; { Place_Marker array element to traverse array with. }
  2994. begin
  2995. for Element := 1 to 10 do
  2996. begin
  2997. if AddCount > 0 then
  2998. begin
  2999. if (Place_Marker[Element] >= Curptr)
  3000. and (Place_Marker[Element] <> 0) then
  3001. Place_Marker[Element] := Place_Marker[Element] + AddCount;
  3002. end
  3003. else
  3004. begin
  3005. if Place_Marker[Element] >= StartPtr then
  3006. begin
  3007. if (Place_Marker[Element] >= StartPtr) and
  3008. (Place_Marker[Element] < EndPtr) then
  3009. Place_marker[Element] := 0
  3010. else
  3011. begin
  3012. if integer (Place_Marker[Element]) - integer (KillCount) > 0 then
  3013. Place_Marker[Element] := Place_Marker[Element] - KillCount
  3014. else
  3015. Place_Marker[Element] := 0;
  3016. end;
  3017. end;
  3018. end;
  3019. end;
  3020. if AddCount > 0 then
  3021. BlankLine := BlankLine + AddCount
  3022. else
  3023. begin
  3024. if integer (BlankLine) - Integer (KillCount) > 0 then
  3025. BlankLine := BlankLine - KillCount
  3026. else
  3027. BlankLine := 0;
  3028. end;
  3029. end; { TEditor.Update_Place_Markers }
  3030. function TEditor.Valid (Command : Word) : Boolean;
  3031. begin
  3032. Valid := IsValid;
  3033. end; { TEditor.Valid }
  3034. {****************************************************************************
  3035. TMEMO
  3036. ****************************************************************************}
  3037. constructor TMemo.Load (var S : Objects.TStream);
  3038. VAR
  3039. Length : Sw_Word;
  3040. begin
  3041. Inherited Load (S);
  3042. S.Read (Length, SizeOf (Length));
  3043. if IsValid then
  3044. begin
  3045. S.Read (Buffer^[BufSize - Length], Length);
  3046. SetBufLen (Length);
  3047. end
  3048. else
  3049. S.Seek (S.GetPos + Length);
  3050. end; { TMemo.Load }
  3051. function TMemo.DataSize : Sw_Word;
  3052. begin
  3053. DataSize := BufSize + SizeOf (Sw_Word);
  3054. end; { TMemo.DataSize }
  3055. procedure TMemo.GetData (var Rec);
  3056. VAR
  3057. Data : TMemoData absolute Rec;
  3058. begin
  3059. Data.Length := BufLen;
  3060. Move (Buffer^, Data.Buffer, CurPtr);
  3061. Move (Buffer^[CurPtr + GapLen], Data.Buffer[CurPtr], BufLen - CurPtr);
  3062. FillChar (Data.Buffer[BufLen], BufSize - BufLen, 0);
  3063. end; { TMemo.GetData }
  3064. function TMemo.GetPalette : PPalette;
  3065. CONST
  3066. P : String[Length (CMemo)] = CMemo;
  3067. begin
  3068. GetPalette := PPalette(@P);
  3069. end; { TMemo.GetPalette }
  3070. procedure TMemo.HandleEvent (var Event : Drivers.TEvent);
  3071. begin
  3072. if (Event.What <> Drivers.evKeyDown) or (Event.KeyCode <> Drivers.kbTab) then
  3073. Inherited HandleEvent (Event);
  3074. end; { TMemo.HandleEvent }
  3075. procedure TMemo.SetData (var Rec);
  3076. VAR
  3077. Data : TMemoData absolute Rec;
  3078. begin
  3079. Move (Data.Buffer, Buffer^[BufSize - Data.Length], Data.Length);
  3080. SetBufLen (Data.Length);
  3081. end; { TMemo.SetData }
  3082. procedure TMemo.Store (var S : Objects.TStream);
  3083. begin
  3084. Inherited Store (S);
  3085. S.Write (BufLen, SizeOf (BufLen));
  3086. S.Write (Buffer^, CurPtr);
  3087. S.Write (Buffer^[CurPtr + GapLen], BufLen - CurPtr);
  3088. end; { TMemo.Store }
  3089. {****************************************************************************
  3090. TFILEEDITOR
  3091. ****************************************************************************}
  3092. constructor TFileEditor.Init (var Bounds : TRect;
  3093. AHScrollBar, AVScrollBar : PScrollBar;
  3094. AIndicator : PIndicator;
  3095. AFileName : FNameStr);
  3096. begin
  3097. Inherited Init (Bounds, AHScrollBar, AVScrollBar, AIndicator, 0);
  3098. if AFileName <> '' then
  3099. begin
  3100. FileName := FExpand (AFileName);
  3101. if IsValid then
  3102. IsValid := LoadFile;
  3103. end;
  3104. end; { TFileEditor.Init }
  3105. constructor TFileEditor.Load (var S : Objects.TStream);
  3106. VAR
  3107. SStart,SEnd,Curs : Sw_Word;
  3108. begin
  3109. Inherited Load (S);
  3110. BufSize := 0;
  3111. S.Read (FileName[0], SizeOf (Byte));
  3112. S.Read (Filename[1], Length (FileName));
  3113. if IsValid then
  3114. IsValid := LoadFile;
  3115. S.Read (SStart, SizeOf (SStart));
  3116. S.Read (SEnd, SizeOf (SEnd));
  3117. S.Read (Curs, SizeOf (Curs));
  3118. if IsValid and (SEnd <= BufLen) then
  3119. begin
  3120. SetSelect (SStart, SEnd, Curs = SStart);
  3121. TrackCursor (True);
  3122. end;
  3123. end; { TFileEditor.Load }
  3124. procedure TFileEditor.DoneBuffer;
  3125. begin
  3126. ReAllocMem(Buffer, 0);
  3127. end; { TFileEditor.DoneBuffer }
  3128. procedure TFileEditor.HandleEvent (var Event : Drivers.TEvent);
  3129. begin
  3130. Inherited HandleEvent (Event);
  3131. case Event.What of
  3132. Drivers.evCommand:
  3133. case Event.Command of
  3134. cmSave : Save;
  3135. cmSaveAs : SaveAs;
  3136. cmSaveDone : if Save then
  3137. Message (Owner, Drivers.evCommand, cmClose, nil);
  3138. else
  3139. Exit;
  3140. end;
  3141. else
  3142. Exit;
  3143. end;
  3144. ClearEvent (Event);
  3145. end; { TFileEditor.HandleEvent }
  3146. procedure TFileEditor.InitBuffer;
  3147. begin
  3148. Assert(Buffer = nil, 'TFileEditor.InitBuffer: Buffer is not nil');
  3149. ReAllocMem(Buffer, MinBufLength);
  3150. BufSize := MinBufLength;
  3151. end; { TFileEditor.InitBuffer }
  3152. function TFileEditor.LoadFile: Boolean;
  3153. VAR
  3154. Length : Sw_Word;
  3155. FSize : Longint;
  3156. FRead : Sw_Integer;
  3157. F : File;
  3158. begin
  3159. LoadFile := False;
  3160. Length := 0;
  3161. Assign(F, FileName);
  3162. Reset(F, 1);
  3163. if IOResult <> 0 then
  3164. EditorDialog(edReadError, @FileName)
  3165. else
  3166. begin
  3167. FSize := FileSize(F);
  3168. if (FSize > MaxBufLength) or not SetBufSize(FSize) then
  3169. EditorDialog(edOutOfMemory, nil)
  3170. else
  3171. begin
  3172. BlockRead(F, Buffer^[BufSize-FSize], FSize, FRead);
  3173. if (IOResult <> 0) or (FRead<>FSize) then
  3174. EditorDialog(edReadError, @FileName)
  3175. else
  3176. begin
  3177. LoadFile := True;
  3178. Length := FRead;
  3179. end;
  3180. end;
  3181. Close(F);
  3182. end;
  3183. SetBufLen(Length);
  3184. end; { TFileEditor.LoadFile }
  3185. function TFileEditor.Save : Boolean;
  3186. begin
  3187. if FileName = '' then
  3188. Save := SaveAs
  3189. else
  3190. Save := SaveFile;
  3191. end; { TFileEditor.Save }
  3192. function TFileEditor.SaveAs : Boolean;
  3193. begin
  3194. SaveAs := False;
  3195. if EditorDialog (edSaveAs, @FileName) <> cmCancel then
  3196. begin
  3197. FileName := FExpand (FileName);
  3198. Message (Owner, Drivers.evBroadcast, cmUpdateTitle, nil);
  3199. SaveAs := SaveFile;
  3200. if IsClipboard then
  3201. FileName := '';
  3202. end;
  3203. end; { TFileEditor.SaveAs }
  3204. function TFileEditor.SaveFile : Boolean;
  3205. VAR
  3206. F : File;
  3207. BackupName : Objects.FNameStr;
  3208. D : DOS.DirStr;
  3209. N : DOS.NameStr;
  3210. E : DOS.ExtStr;
  3211. begin
  3212. SaveFile := False;
  3213. if Flags and efBackupFiles <> 0 then
  3214. begin
  3215. FSplit (FileName, D, N, E);
  3216. BackupName := D + N + '.bak';
  3217. Assign (F, BackupName);
  3218. Erase (F);
  3219. Assign (F, FileName);
  3220. Rename (F, BackupName);
  3221. InOutRes := 0;
  3222. end;
  3223. Assign (F, FileName);
  3224. Rewrite (F, 1);
  3225. if IOResult <> 0 then
  3226. EditorDialog (edCreateError, @FileName)
  3227. else
  3228. begin
  3229. BlockWrite (F, Buffer^, CurPtr);
  3230. BlockWrite (F, Buffer^[CurPtr + GapLen], BufLen - CurPtr);
  3231. if IOResult <> 0 then
  3232. EditorDialog (edWriteError, @FileName)
  3233. else
  3234. begin
  3235. Modified := False;
  3236. Update (ufUpdate);
  3237. SaveFile := True;
  3238. end;
  3239. Close (F);
  3240. end;
  3241. end; { TFileEditor.SaveFile }
  3242. function TFileEditor.SetBufSize (NewSize : Sw_Word) : Boolean;
  3243. VAR
  3244. N : Sw_Word;
  3245. begin
  3246. SetBufSize := False;
  3247. if NewSize = 0 then
  3248. NewSize := MinBufLength
  3249. else
  3250. if NewSize > (MaxBufLength-MinBufLength) then
  3251. NewSize := MaxBufLength
  3252. else
  3253. NewSize := (NewSize + (MinBufLength-1)) and (MaxBufLength and (not (MinBufLength-1)));
  3254. if NewSize <> BufSize then
  3255. begin
  3256. if NewSize > BufSize then ReAllocMem(Buffer, NewSize);
  3257. N := BufLen - CurPtr + DelCount;
  3258. Move(Buffer^[BufSize - N], Buffer^[NewSize - N], N);
  3259. if NewSize < BufSize then ReAllocMem(Buffer, NewSize);
  3260. BufSize := NewSize;
  3261. GapLen := BufSize - BufLen;
  3262. end;
  3263. SetBufSize := True;
  3264. end; { TFileEditor.SetBufSize }
  3265. procedure TFileEditor.Store (var S : Objects.TStream);
  3266. begin
  3267. Inherited Store (S);
  3268. S.Write (FileName, Length (FileName) + 1);
  3269. S.Write (SelStart, SizeOf (SelStart));
  3270. S.Write (SelEnd, SizeOf (SelEnd));
  3271. S.Write (CurPtr, SizeOf (CurPtr));
  3272. end; { TFileEditor.Store }
  3273. procedure TFileEditor.UpdateCommands;
  3274. begin
  3275. Inherited UpdateCommands;
  3276. SetCmdState (cmSave, True);
  3277. SetCmdState (cmSaveAs, True);
  3278. SetCmdState (cmSaveDone, True);
  3279. end; { TFileEditor.UpdateCommands }
  3280. function TFileEditor.Valid (Command : Word) : Boolean;
  3281. VAR
  3282. D : Integer;
  3283. begin
  3284. if Command = cmValid then
  3285. Valid := IsValid
  3286. else
  3287. begin
  3288. Valid := True;
  3289. if Modified then
  3290. begin
  3291. if FileName = '' then
  3292. D := edSaveUntitled
  3293. else
  3294. D := edSaveModify;
  3295. case EditorDialog (D, @FileName) of
  3296. cmYes : Valid := Save;
  3297. cmNo : Modified := False;
  3298. cmCancel : Valid := False;
  3299. end;
  3300. end;
  3301. end;
  3302. end; { TFileEditor.Valid }
  3303. {****************************************************************************
  3304. TEDITWINDOW
  3305. ****************************************************************************}
  3306. constructor TEditWindow.Init (var Bounds : TRect;
  3307. FileName : Objects.FNameStr;
  3308. ANumber : Integer);
  3309. var
  3310. HScrollBar : PScrollBar;
  3311. VScrollBar : PScrollBar;
  3312. Indicator : PIndicator;
  3313. R : TRect;
  3314. begin
  3315. Inherited Init (Bounds, '', ANumber);
  3316. Options := Options or ofTileable;
  3317. R.Assign (18, Size.Y - 1, Size.X - 2, Size.Y);
  3318. HScrollBar := New (PScrollBar, Init (R));
  3319. HScrollBar^.Hide;
  3320. Insert (HScrollBar);
  3321. R.Assign (Size.X - 1, 1, Size.X, Size.Y - 1);
  3322. VScrollBar := New (PScrollBar, Init (R));
  3323. VScrollBar^.Hide;
  3324. Insert (VScrollBar);
  3325. R.Assign (2, Size.Y - 1, 16, Size.Y);
  3326. Indicator := New (PIndicator, Init (R));
  3327. Indicator^.Hide;
  3328. Insert (Indicator);
  3329. GetExtent (R);
  3330. R.Grow (-1, -1);
  3331. Editor := New (PFileEditor, Init (R, HScrollBar, VScrollBar, Indicator, FileName));
  3332. Insert (Editor);
  3333. end; { TEditWindow.Init }
  3334. constructor TEditWindow.Load (var S : Objects.TStream);
  3335. begin
  3336. Inherited Load (S);
  3337. GetSubViewPtr (S, Editor);
  3338. end; { TEditWindow.Load }
  3339. procedure TEditWindow.Close;
  3340. begin
  3341. if Editor^.IsClipboard then
  3342. Hide
  3343. else
  3344. Inherited Close;
  3345. end; { TEditWindow.Close }
  3346. function TEditWindow.GetTitle (MaxSize : Sw_Integer) : TTitleStr;
  3347. begin
  3348. if Editor^.IsClipboard then
  3349. GetTitle := sClipboard
  3350. else
  3351. if Editor^.FileName = '' then
  3352. GetTitle := sUntitled
  3353. else
  3354. GetTitle := Editor^.FileName;
  3355. end; { TEditWindow.GetTile }
  3356. procedure TEditWindow.HandleEvent (var Event : Drivers.TEvent);
  3357. begin
  3358. Inherited HandleEvent (Event);
  3359. if (Event.What = Drivers.evBroadcast) then
  3360. { and (Event.Command = cmUpdateTitle) then }
  3361. { Changed if statement above so I could test for cmBlugeonStats. }
  3362. { Stats would not show up when loading a file until a key was pressed. }
  3363. case Event.Command of
  3364. cmUpdateTitle :
  3365. begin
  3366. Frame^.DrawView;
  3367. ClearEvent (Event);
  3368. end;
  3369. cmBludgeonStats :
  3370. begin
  3371. Editor^.Update (ufStats);
  3372. ClearEvent (Event);
  3373. end;
  3374. end;
  3375. end; { TEditWindow.HandleEvent }
  3376. procedure TEditWindow.SizeLimits(var Min, Max: TPoint);
  3377. begin
  3378. inherited SizeLimits(Min, Max);
  3379. Min.X := 23;
  3380. end;
  3381. procedure TEditWindow.Store (var S : Objects.TStream);
  3382. begin
  3383. Inherited Store (S);
  3384. PutSubViewPtr (S, Editor);
  3385. end; { TEditWindow.Store }
  3386. procedure RegisterEditors;
  3387. begin
  3388. RegisterType (REditor);
  3389. RegisterType (RMemo);
  3390. RegisterType (RFileEditor);
  3391. RegisterType (RIndicator);
  3392. RegisterType (REditWindow);
  3393. end; { RegisterEditors }
  3394. end. { Unit NewEdit }