Listing: 1 IMPLEMENTATION MODULE Editor; 2 (* 3 * REPERTOIRE 4 * Release 1.6 5 * By Charles Bradford and Cole Brecheen 6 * (c) Copyright 1985-1992 PMI 7 * Green Bay, Wisconsin 8 * All rights reserved 9 * (414) 468-6040 10 * 11 * $Header: D:/logfiles/mods/editor.mov 1.7 10 Mar 1991 15:26:46 coleb $ 12 * 13 *) 14 15 16 (*$O-*) 17 (*We turn off optimization for the whole module to help avoid bugs in 18 Logitech's LONGINTs.*) 19 20 21 (*EntryDiag: 22 IMPORT Diagnostics; 23 :EntryDiag*) 24 25 IMPORT BigSets; 26 IMPORT ByteFiddler; 27 IMPORT GenLists; 28 IMPORT KbdInput; 29 IMPORT Key; 30 IMPORT ListUtils; 31 IMPORT LowLevel; 32 IMPORT M2Strings; 33 IMPORT MsColors; 34 IMPORT Numbers; 35 IMPORT NumTypes; 36 IMPORT PosUtils; 37 IMPORT ScrnTypes; 38 IMPORT ScrnUtl1; 39 IMPORT Spkr; 40 IMPORT StrConv; 41 IMPORT StrEdit; 42 IMPORT SYSTEM; 43 IMPORT UserOps; 44 IMPORT VEditor; 45 IMPORT VWindows; 46 47 48 VAR 49 Initialized : BOOLEAN; 50 51 52 CONST 53 LineLeng = 255; 54 DisplayLeng = 80; 55 56 TYPE 57 LineType = ARRAY [0..LineLeng] OF CHAR; ***** ^ not supported yet ***** ^ not supported yet 58 LongAndShort = 59 RECORD 60 CASE : BOOLEAN OF ***** ^ not supported yet ***** ^ 'POINTER' expected 61 TRUE: longi: LONGINT; 62 | FALSE: locard, hicard: CARDINAL; 63 END; 64 END; 65 66 VAR 67 DumType: CARDINAL; 68 blank : ARRAY [0..0] OF CHAR; 69 DeleteBuffer : GenLists.GenList; 70 71 72 PROCEDURE CountToStr( TheCount: LongAndShort; 73 VAR TheStr: ARRAY OF CHAR); 74 BEGIN 75 IF TheCount.hicard = 0 THEN 76 StrConv.CardinalToStr( TheCount.locard, 1, TheStr); 77 ELSE 78 StrConv.LongIntegerToStr( TheCount.longi, 1, TheStr); 79 END; 80 END CountToStr; 81 82 83 PROCEDURE DefaultEditor( VAR TheList: GenLists.GenList; 84 VAR Rec: VEditor.AnEdControlRec ); 85 86 TYPE 87 WriteToScreenOrNot = (DoWrite, DontWrite); 88 VAR 89 BlankStr : ARRAY [0..DisplayLeng] OF CHAR; 90 Testing, DoExitBox : BOOLEAN; 91 (* Testing is true if want to see internals printed. *) 92 WindowHeight, ColsScrolled, MaxLength, 93 LastLineDeleted, TheRow, RLineCnt, TLine, 94 TheNdx : CARDINAL; 95 RCharCnt, TCharCnt : LongAndShort; 96 (* TheRow = the actual row on the screen where the cursor 97 is*) 98 (* Row1 = first row on screen that is in the editor*) 99 (* TheNdx = the column in the text, not on the screen, 100 where we are. Value starts at 0. TheNdx + Col1 is the 101 actual screen column*) 102 (* RCharCnt, RlineCnt = actual text size in characters and 103 lines*) 104 (* TCharCnt, Tline = cursor position in text (characters & 105 lines)*) 106 dumint: INTEGER; 107 108 109 PROCEDURE SetPromptColors( TheFrame: ScrnTypes.DisplayFrame ); 110 BEGIN 111 VWindows.SetForeColor( TheFrame^.WindowHandle, 112 Rec.EdPromptFore ); 113 VWindows.SetBackColor( TheFrame^.WindowHandle, 114 Rec.EdPromptBack ); 115 VWindows.SetMonoAttr( TheFrame^.WindowHandle, 116 Rec.EdPromptAttrib ); 117 END SetPromptColors; 118 119 120 PROCEDURE SetAttribOrColor( ForeColor, BackColor: MsColors.AColor; 121 attr: MsColors.AMonoAttribute ); 122 BEGIN 123 VWindows.SetForeColor( Rec.WindowHandle, ForeColor ); 124 VWindows.SetBackColor( Rec.WindowHandle, BackColor ); 125 VWindows.SetMonoAttr( Rec.WindowHandle, attr ); 126 END SetAttribOrColor; 127 128 129 PROCEDURE CheckMax(): BOOLEAN; 130 BEGIN 131 IF (Rec.MaxLines = 0) OR 132 (GenLists.ListLength( TheList ) < Rec.MaxLines) THEN 133 RETURN TRUE; 134 ELSE 135 Spkr.Noise( Spkr.Warble, Spkr.Normal, Spkr.Short); 136 RETURN FALSE; 137 END; 138 END CheckMax; 139 140 PROCEDURE UpdateFrameRec(); 141 VAR 142 FieldRec: ScrnTypes.InputFieldRecord; 143 BEGIN 144 IF Rec.FrameRec # NIL THEN 145 IF GenLists.Initialized( Rec.FrameRec^.FieldList ) AND 146 (Rec.FrameRec^.CurrentField # 0) AND 147 (GenLists.ListLength( Rec.FrameRec^.FieldList ) > 0) THEN 148 IF (Rec.FrameRec^.CurrentField = 0) THEN 149 Rec.FrameRec^.CurrentField := 1; 150 END; 151 ScrnUtl1.GetFieldRec( Rec.FrameRec, Rec.FrameRec^.CurrentField, 152 FieldRec ); 153 IF FieldRec.typ = ScrnTypes.EditorCode THEN 154 (* 155 ?? 156 FieldRec.Col2 := Rec.Col2; 157 FieldRec.Row2 := Rec.Row2; 158 *) 159 FieldRec.TextRow1 := Rec.TextRow1; 160 FieldRec.CursorCol := Rec.CursorCol; 161 FieldRec.CursorRow := Rec.CursorRow; 162 FieldRec.MaxLines := Rec.MaxLines; 163 FieldRec.ChangeMade := Rec.ChangeMade; 164 FieldRec.ReadOnly := Rec.ReadOnly; 165 ScrnUtl1.PutFieldRec( FieldRec, Rec.FrameRec, 166 Rec.FrameRec^.CurrentField ); 167 END; 168 END; 169 END; 170 END UpdateFrameRec; 171 172 PROCEDURE GetFrameRecData(); 173 VAR 174 FieldRec: ScrnTypes.InputFieldRecord; 175 BEGIN 176 IF Rec.FrameRec # NIL THEN 177 Rec.WindowHandle := Rec.FrameRec^.WindowHandle; 178 IF GenLists.Initialized( Rec.FrameRec^.FieldList ) AND 179 (GenLists.ListLength( Rec.FrameRec^.FieldList ) > 0) THEN 180 IF (Rec.FrameRec^.CurrentField = 0) THEN 181 Rec.FrameRec^.CurrentField := 1; 182 END; 183 ScrnUtl1.GetFieldRec( Rec.FrameRec, Rec.FrameRec^.CurrentField, 184 FieldRec ); 185 IF FieldRec.typ = ScrnTypes.EditorCode THEN 186 (* 187 ?? 188 Rec.Col2 := FieldRec.Col2; 189 Rec.Row2 := FieldRec.Row2; 190 *) 191 Rec.TextRow1 := FieldRec.TextRow1; 192 Rec.CursorCol := FieldRec.CursorCol; 193 Rec.CursorRow := FieldRec.CursorRow; 194 Rec.MaxLines := FieldRec.MaxLines; 195 Rec.ChangeMade := FieldRec.ChangeMade; 196 Rec.ReadOnly := FieldRec.ReadOnly; 197 IF NOT ScrnUtl1.ListFromEdField( Rec.FrameRec, 198 Rec.FrameRec^.CurrentField, TheList ) THEN 199 (*Remember that a user might invoke a help sequence from 200 within the editor, which would require PushFrame/PopFrame 201 to save and restore the frame's lists. Since we're editing 202 one of them, we need to update our pointer, because the 203 saved copy will be in a different place.*) 204 END; 205 END; 206 END; 207 END; 208 END GetFrameRecData; 209 210 PROCEDURE findindent(str : ARRAY OF CHAR) : CARDINAL; 211 VAR 212 ind, leng : CARDINAL; 213 done : BOOLEAN; 214 BEGIN 215 done := FALSE; 216 ind := 0; 217 leng := M2Strings.Length(str); 218 IF leng#0 THEN 219 DEC(leng); 220 REPEAT 221 IF (str[ind]#blank[0]) THEN 222 done := TRUE; 223 ELSIF (ind>=leng) THEN 224 done := TRUE; 225 ind := HIGH(str) + 1; 226 ELSE 227 INC(ind); 228 END; 229 UNTIL done; 230 ELSE 231 ind := HIGH(str) + 1; 232 END; 233 RETURN (ind); 234 END findindent; 235 236 PROCEDURE WriteStrings(TextLine, baserow, endrow : CARDINAL); 237 VAR 238 clrstr: ARRAY [0..DisplayLeng] OF CHAR; 239 clrlngth, tmpsize, leng, tmprow : CARDINAL; 240 tmpadr: SYSTEM.ADDRESS; 241 BEGIN 242 LowLevel.Fill( SYSTEM.ADR(clrstr), DisplayLeng + 1, blank); 243 leng := GenLists.ListLength( TheList); 244 M2Strings.Assign(BlankStr, clrstr); 245 tmprow := baserow - 1; 246 WHILE (TextLine <= leng) AND (tmprow < endrow) DO 247 INC( tmprow); 248 GenLists.GetElmtAdr( TheList, TextLine, tmpadr, tmpsize, DumType); 249 tmpsize := LowLevel.ScanEQ( tmpsize, 0C, tmpadr ); 250 IF tmpsize < ColsScrolled THEN 251 clrlngth := MaxLength; 252 tmpsize := 0; 253 (*set tmpsize to 0 because none of the string will 254 show.*) 255 ELSE 256 IF (tmpsize - ColsScrolled) > MaxLength THEN 257 tmpsize := MaxLength; 258 clrlngth := 0; 259 ELSE 260 tmpsize := Numbers.Min( tmpsize - ColsScrolled, MaxLength ); 261 clrlngth := MaxLength - tmpsize; 262 END; 263 IF tmpsize > 0 THEN 264 VWindows.DrawStr( Rec.WindowHandle, Rec.Col1, 265 tmprow, LowLevel.AddAddr(tmpadr, ColsScrolled), 266 tmpsize ); 267 END; 268 END; 269 IF clrlngth > 0 THEN 270 VWindows.DrawStr( Rec.WindowHandle, 271 Rec.Col1 + tmpsize, tmprow, SYSTEM.ADR(clrstr), 272 clrlngth ); 273 END; 274 INC( TextLine); 275 END; 276 IF (tmprow < endrow) AND (endrow = Rec.Row2) THEN 277 VWindows.ClearPart( Rec.WindowHandle, 278 Rec.Col1, tmprow + 1, Rec.Col2, Rec.Row2); 279 END; 280 END WriteStrings; 281 282 PROCEDURE OvrOrIns( VAR TheStr: ARRAY OF CHAR); 283 BEGIN 284 IF Rec.overwriting THEN 285 StrEdit.AssignStr( 'Overwrite', TheStr); 286 ELSE 287 StrEdit.AssignStr( ' Insert ', TheStr); 288 END; 289 END OvrOrIns; 290 291 PROCEDURE WriteFooter(); 292 VAR 293 dumstr : ARRAY [0..DisplayLeng] OF CHAR; 294 tmpstr : ARRAY [0..10] OF CHAR; 295 SavedFore, SavedBack : MsColors.AColor; 296 SavedAttr : MsColors.AMonoAttribute; 297 BEGIN 298 IF Rec.FrameRec # NIL THEN 299 SavedFore := VWindows.ForeColor( Rec.WindowHandle ); 300 SavedBack := VWindows.BackColor( Rec.WindowHandle ); 301 SavedAttr := VWindows.MonoAttr( Rec.WindowHandle ); 302 SetPromptColors( Rec.FrameRec ); 303 END; 304 CountToStr(RCharCnt, tmpstr); 305 M2Strings.Concat('TEXT SIZE: chars:', tmpstr, dumstr); 306 StrEdit.LeftJustify( dumstr, 23 ); 307 StrEdit.Append(dumstr, ' lines:'); 308 StrConv.CardinalToStr(RLineCnt, 1, tmpstr); 309 StrEdit.Append(dumstr, tmpstr); 310 StrEdit.LeftJustify( dumstr, 33 ); 311 StrEdit.Append(dumstr, ' POSITION: char:'); 312 CountToStr( TCharCnt, tmpstr); 313 StrEdit.Append(dumstr, tmpstr); 314 StrEdit.LeftJustify( dumstr, 54 ); 315 StrEdit.Append(dumstr, ' line:'); 316 StrConv.CardinalToStr(TLine, 1, tmpstr); 317 StrEdit.Append(dumstr, tmpstr); 318 StrEdit.LeftJustify( dumstr, 65 ); 319 StrEdit.Append(dumstr, 'MODE:'); 320 OvrOrIns( tmpstr); 321 StrEdit.Append(dumstr, tmpstr); 322 VWindows.DrawStr( Rec.WindowHandle,2, Rec.CountRow, 323 SYSTEM.ADR(dumstr), M2Strings.Length(dumstr) ); 324 IF Rec.FrameRec # NIL THEN 325 VWindows.SetForeColor( Rec.WindowHandle, SavedFore ); 326 VWindows.SetBackColor( Rec.WindowHandle, SavedBack ); 327 VWindows.SetMonoAttr( Rec.WindowHandle, SavedAttr ); 328 END; 329 END WriteFooter; 330 331 PROCEDURE AddCLCount( CharTotalDiff: LONGINT; LineTotalDiff: INTEGER; 332 CharPosDiff: LONGINT; LinePosDiff : INTEGER ); 333 VAR 334 tmpstr : ARRAY [0..20] OF CHAR; 335 TmpLong : LONGINT; 336 SavedFore, SavedBack : MsColors.AColor; 337 SavedAttr : MsColors.AMonoAttribute; 338 BEGIN 339 TLine := INTEGER( INTEGER(TLine) + LinePosDiff ); 340 IF Rec.DoCounting THEN 341 IF Rec.FrameRec # NIL THEN 342 SavedFore := VWindows.ForeColor( Rec.WindowHandle ); 343 SavedBack := VWindows.BackColor( Rec.WindowHandle ); 344 SavedAttr := VWindows.MonoAttr( Rec.WindowHandle ); 345 SetPromptColors( Rec.FrameRec ); 346 END; 347 IF LineTotalDiff # 0 THEN 348 RLineCnt := INTEGER(INTEGER(RLineCnt) + LineTotalDiff); 349 StrConv.CardinalToStr(RLineCnt, 1, tmpstr); 350 StrEdit.Append(tmpstr, ' '); 351 StrEdit.SetLength(tmpstr, 4); 352 VWindows.DrawStr( Rec.WindowHandle, 31, 353 Rec.CountRow, SYSTEM.ADR(tmpstr), 4); 354 END; 355 IF LinePosDiff#0 THEN 356 StrConv.CardinalToStr(TLine, 1, tmpstr); 357 StrEdit.Append(tmpstr, ' '); 358 StrEdit.SetLength(tmpstr, 4); 359 VWindows.DrawStr( Rec.WindowHandle,62, Rec.CountRow, 360 SYSTEM.ADR(tmpstr), 4); 361 END; 362 IF CharTotalDiff # NumTypes.L0 THEN 363 TmpLong := CharTotalDiff; 364 RCharCnt.longi := RCharCnt.longi + TmpLong; 365 CountToStr( RCharCnt, tmpstr); 366 StrEdit.Append(tmpstr, ' '); 367 StrEdit.SetLength(tmpstr, 5); 368 VWindows.DrawStr( Rec.WindowHandle,19, Rec.CountRow, 369 SYSTEM.ADR(tmpstr), 5); 370 END; 371 IF CharPosDiff # NumTypes.L0 THEN 372 TmpLong := CharPosDiff; 373 TCharCnt.longi := TCharCnt.longi + TmpLong; 374 CountToStr( TCharCnt, tmpstr); 375 StrEdit.Append(tmpstr, ' '); 376 StrEdit.SetLength(tmpstr, 5); 377 VWindows.DrawStr( Rec.WindowHandle,51, Rec.CountRow, 378 SYSTEM.ADR(tmpstr), 5); 379 END; 380 IF Rec.FrameRec # NIL THEN 381 VWindows.SetForeColor( Rec.WindowHandle, SavedFore ); 382 VWindows.SetBackColor( Rec.WindowHandle, SavedBack ); 383 VWindows.SetMonoAttr( Rec.WindowHandle, SavedAttr ); 384 END; 385 END; 386 VWindows.GotoXY( Rec.WindowHandle, Rec.Col1 + 387 TheNdx - ColsScrolled, TheRow); 388 END AddCLCount; 389 390 PROCEDURE CountChars(Rtmptr : CARDINAL; VAR Rchars : LONGINT; 391 VAR Rlines : CARDINAL; Ttmptr : CARDINAL; 392 VAR Tchars : LONGINT); 393 VAR 394 leng : CARDINAL; 395 BEGIN 396 IF NOT Rec.DoCounting THEN 397 Rchars := NumTypes.L1; 398 Rlines := 1; 399 Tchars := NumTypes.L1; 400 (*Added 25 May 87 to prevent uninitialized values*) 401 RETURN; 402 END; 403 leng := GenLists.ListLength( TheList); 404 (*count all chars starting WITH Rtmptr*) 405 Rlines := 0; 406 Rchars := NumTypes.L1; 407 (*put 1+ chars and lines before Ttmptr in Tchars and Tlines*) 408 Tchars := NumTypes.L1; 409 WHILE Rtmptr <= leng DO 410 Rlines := Rlines + 1; 411 IF Rtmptr=Ttmptr THEN 412 Tchars := Rchars; 413 END; 414 Rchars := Rchars + Numbers.Lc( ListUtils.ElmtSize(TheList,Rtmptr) + 2 ); 415 INC( Rtmptr); 416 END; 417 END CountChars; 418 419 420 PROCEDURE TheLength(): CARDINAL; 421 (* Returns length of current line *) 422 BEGIN 423 RETURN ListUtils.ElmtSize( TheList, TLine); 424 END TheLength; 425 426 427 PROCEDURE MoveAcrossTo(NewNdx : INTEGER); 428 VAR 429 charsmoved : INTEGER; 430 redraw : BOOLEAN; 431 lngth : CARDINAL; 432 BEGIN 433 lngth := TheLength(); 434 IF (CARDINAL(NewNdx) >= lngth) AND (TheNdx >= lngth) THEN 435 charsmoved := 0; 436 ELSE 437 IF (CARDINAL(NewNdx) >= lngth) AND 438 (TheNdx < lngth) THEN 439 (*We've crossed over to the right of the trailing CR/LF.*) 440 charsmoved := (lngth - TheNdx) + 2; 441 ELSIF (CARDINAL(NewNdx) < lngth) AND 442 (TheNdx >= lngth) THEN 443 (*We've crossed over to the left of the trailing CR/LF.*) 444 charsmoved := (NewNdx - INTEGER(lngth)) - 2; 445 ELSE 446 charsmoved := NewNdx - INTEGER(TheNdx); 447 IF (charsmoved = 0) THEN 448 RETURN; 449 END; 450 END; 451 END; 452 TheNdx := NewNdx; 453 IF (TheNdx < ColsScrolled) THEN 454 ColsScrolled := TheNdx; 455 redraw := TRUE; 456 ELSIF (TheNdx > (ColsScrolled + MaxLength - 1)) THEN 457 ColsScrolled := TheNdx - MaxLength + 1; 458 redraw := TRUE; 459 ELSE 460 redraw := FALSE; 461 END; 462 AddCLCount( NumTypes.L0, 0, Numbers.Li(charsmoved), 0); 463 IF redraw THEN 464 WriteStrings( TLine - 465 (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); 466 END; 467 END MoveAcrossTo; 468 469 470 PROCEDURE MoveVerticallyTo( NewTLine: CARDINAL ); 471 VAR 472 TmpSize, ColNow, RowNow, LstLngth, TmpLineCount : CARDINAL; 473 TmpL, BytesSkipped : LONGINT; 474 redrawing, MovingUp : BOOLEAN; 475 addrow, addchar, dist : INTEGER; 476 BEGIN 477 LstLngth := GenLists.ListLength( TheList ); 478 addrow := 0; 479 addchar := 0; 480 IF NewTLine > LstLngth THEN 481 (*We'll add a line if the line we're on is the last line 482 and it isn't blank.*) 483 IF (TLine = LstLngth) AND 484 (ListUtils.ElmtSize(TheList, TLine) > 0) THEN 485 IF CheckMax() THEN 486 GenLists.ListInsert( '', DumType, TheList, TLine + 1); 487 addrow := 1; 488 addchar := 2; 489 INC( LstLngth ); 490 END; 491 END; 492 (*otherwise we don't let them move past last line*) 493 NewTLine := LstLngth; 494 ELSIF NewTLine < 1 THEN 495 NewTLine := 1; 496 END; 497 IF TLine > NewTLine THEN 498 MovingUp := TRUE; 499 ELSIF TLine < NewTLine THEN 500 MovingUp := FALSE; 501 ELSE 502 RETURN; 503 END; 504 505 (*Now we count the bytes we will be skipping.*) 506 TmpLineCount := TLine; 507 BytesSkipped := NumTypes.L0; 508 IF MovingUp THEN 509 WHILE (TmpLineCount >= NewTLine) DO 510 IF TmpLineCount > LstLngth THEN 511 (*This can happen if we've just deleted the last line 512 and we're moving up to what is now the new last line.*) 513 TmpL := NumTypes.L0; 514 ELSE 515 TmpL := Numbers.Lc( ListUtils.ElmtSize( TheList, 516 TmpLineCount )); 517 (*Workaround for a Logitech LONGINT bug.*) 518 END; 519 BytesSkipped := BytesSkipped + TmpL + NumTypes.L2; 520 DEC( TmpLineCount ); 521 END; 522 (*Adjust BytesSkipped because we may not have actually skipped 523 over some of the bytes on the line we were on. It depends 524 on whether the cursor was beyond the end of the line at the 525 time.*) 526 IF TLine > LstLngth THEN 527 TmpSize := 0; 528 ELSE 529 TmpSize := ListUtils.ElmtSize( TheList, TLine ); 530 END; 531 IF TheNdx < TmpSize THEN 532 TmpSize := TmpSize - TheNdx + 2; 533 (*Otherwise the cursor was beyond the end of the line, so 534 we did skip over the full length of the line plus the 535 CR/LF at the end of it. We don't have to subtract 536 anything*) 537 BytesSkipped := BytesSkipped - Numbers.Lc(TmpSize); 538 END; 539 TmpSize := ListUtils.ElmtSize( TheList, NewTLine ); 540 (*Now determine whether we have skipped over all 541 of the line we're moving to. If we don't adjust 542 BytesSkipped, it tells AddCLCount that we have 543 skipped over the whole thing.*) 544 IF TheNdx < TmpSize THEN 545 BytesSkipped := BytesSkipped - Numbers.Lc(TheNdx); 546 ELSE 547 TmpSize := TmpSize + 2; 548 BytesSkipped := BytesSkipped - Numbers.Lc(TmpSize); 549 END; 550 BytesSkipped := -BytesSkipped; 551 ELSE 552 WHILE (TmpLineCount <= NewTLine) DO 553 TmpL := Numbers.Lc( ListUtils.ElmtSize( TheList, TmpLineCount )); 554 (*Workaround for a Logitech LONGINT bug.*) 555 BytesSkipped := BytesSkipped + TmpL + NumTypes.L2; 556 INC( TmpLineCount ); 557 END; 558 (*Now we subtract the part of the line we're on that we didn't 559 actually skip.*) 560 IF TLine <= LstLngth THEN 561 TmpL := Numbers.Lc( Numbers.Min(TheNdx, TheLength() ) ); 562 IF Numbers.C(TmpL) >= ListUtils.ElmtSize(TheList, TLine) THEN 563 TmpL := TmpL + NumTypes.L2; 564 END; 565 BytesSkipped := BytesSkipped - TmpL; 566 END; 567 (*And now we subtract the part of the new line that we haven't 568 yet skipped.*) 569 TmpSize := ListUtils.ElmtSize(TheList, NewTLine); 570 IF TheNdx < TmpSize THEN 571 TmpSize := TmpSize - TheNdx + 2; 572 BytesSkipped := BytesSkipped - Numbers.Lc(TmpSize); 573 END; 574 END; 575 576 dist := INTEGER(NewTLine) - INTEGER(TLine); 577 578 (*Now determine whether we can get by with just moving the cursor 579 instead of redrawing some or all of the window.*) 580 IF MovingUp THEN 581 redrawing := (INTEGER(TheRow) + dist) < INTEGER(Rec.Row1); 582 ELSE 583 redrawing := (INTEGER(TheRow) + dist) > INTEGER(Rec.Row2); 584 END; 585 IF NOT redrawing THEN 586 TheRow := INTEGER(INTEGER(TheRow) + dist); 587 VWindows.GetCursorCoords( Rec.WindowHandle, 588 ColNow, RowNow ); 589 VWindows.GotoXY( Rec.WindowHandle, ColNow, 590 CARDINAL(INTEGER(RowNow) + dist) ); 591 AddCLCount( Numbers.Li(addchar), addrow, BytesSkipped, dist ); 592 RETURN; 593 END; 594 595 (*We know we have to redraw at least some of the window. The 596 next easy case is redrawing the whole thing.*) 597 IF ABS(dist) >= INTEGER(WindowHeight) THEN 598 IF (NewTLine > (TheRow - Rec.Row1)) AND 599 (NOT (NewTLine = LstLngth)) THEN 600 WriteStrings( NewTLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); 601 ELSE 602 (*We're moving more than a page's length, so we'll position the 603 cursor to the top of the window unless we're going to the 604 very end--in that case we position it to the bottom.*) 605 VWindows.GetCursorCoords( Rec.WindowHandle, 606 ColNow, RowNow ); 607 IF (NewTLine = LstLngth) AND (NewTLine >= WindowHeight) THEN 608 WriteStrings( NewTLine - WindowHeight + 1, Rec.Row1, Rec.Row2 ); 609 TheRow := Rec.Row2; 610 VWindows.GotoXY( Rec.WindowHandle, ColNow, 611 Rec.Row2 ); 612 ELSE 613 WriteStrings( NewTLine, Rec.Row1, Rec.Row2 ); 614 TheRow := Rec.Row1; 615 VWindows.GotoXY( Rec.WindowHandle, ColNow, 616 Rec.Row1 ); 617 END; 618 END; 619 AddCLCount( Numbers.Li(addchar), addrow, BytesSkipped, dist ); 620 RETURN; 621 END; 622 623 (*Looks like we'll have to scroll part of the window and redraw 624 the rest of it.*) 625 IF NOT VWindows.ScrollVertically( Rec.WindowHandle, 626 Rec.Col1, Rec.Row1, Rec.Col2, Rec.Row2, dist ) THEN 627 (*The window manager they've chosen doesn't support a 628 fast vertical scroll, so we can redraw the whole thing 629 and leave.*) 630 WriteStrings( NewTLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); 631 AddCLCount( Numbers.Li(addchar), addrow, BytesSkipped, dist ); 632 RETURN; 633 END; 634 635 IF MovingUp THEN 636 (*We have to redraw the top of the window.*) 637 WriteStrings( NewTLine - (TheRow - Rec.Row1), Rec.Row1, 638 Rec.Row1 + CARDINAL(ABS(dist)) - 1 ); 639 ELSE 640 (*We have to redraw the bottom of the window.*) 641 WriteStrings( NewTLine - CARDINAL(ABS(dist)) + 1, 642 Rec.Row2 - CARDINAL(ABS(dist)) + 1, Rec.Row2 ); 643 END; 644 AddCLCount( Numbers.Li(addchar), addrow, BytesSkipped, dist ); 645 END MoveVerticallyTo; 646 647 648 PROCEDURE PageUp(); 649 BEGIN 650 IF (TheRow > Rec.Row1) OR (TLine = 1) THEN 651 MoveVerticallyTo( TLine - (TheRow - Rec.Row1) ); 652 ELSIF WindowHeight >= TLine THEN 653 MoveVerticallyTo( 1 ); 654 ELSE 655 MoveVerticallyTo( TLine - WindowHeight ); 656 END; 657 END PageUp; 658 659 PROCEDURE PageDown(); 660 BEGIN 661 IF (TheRow < Rec.Row2) OR (TLine = GenLists.ListLength(TheList)) THEN 662 MoveVerticallyTo( TLine + (Rec.Row2 - TheRow) ); 663 ELSE 664 MoveVerticallyTo( TLine + WindowHeight ); 665 END; 666 END PageDown; 667 668 669 PROCEDURE DeleteAChar( spacesback : CARDINAL); 670 VAR 671 tmpadr: SYSTEM.ADDRESS; 672 null: CHAR; 673 tmpsize, NewNdx: CARDINAL; 674 BEGIN 675 null := 0C; 676 IF TheNdx > TheLength() THEN 677 MoveAcrossTo( TheLength() ); 678 END; 679 NewNdx := TheNdx - spacesback; 680 MoveAcrossTo( NewNdx ); 681 (*This changes the value of TheNdx. We have to do it 682 before the ShiftArrayLeft because MoveAcrossTo won't 683 update our character position if it thinks we're 684 moving around in the void beyond the end of the line.*) 685 GenLists.GetElmtAdr( TheList, TLine, tmpadr, tmpsize, DumType); 686 LowLevel.ShiftArrayLeft( LowLevel.AddAddr(tmpadr, NewNdx), 687 tmpsize - NewNdx, 1 ); 688 (*Now we have to make sure we've truncated the line, because 689 the ShiftArrayLeft will only do so if it moves a trailing 690 null with the rest of the string.*) 691 IF tmpsize > 0 THEN 692 ListUtils.OverwriteElmt( TheList, TLine, SYSTEM.ADR(null), 1, 693 tmpsize - 1 ); 694 END; 695 WriteStrings( TLine, TheRow, TheRow ); 696 IF NewNdx >= TheLength() THEN 697 (*We have to increment the character position by 2 if we 698 wound up beyond the line length--the MoveAcrossTo didn't 699 know what the ending line length would be.*) 700 AddCLCount( Numbers.Li(-1), 0, NumTypes.L2, 0); 701 ELSE 702 AddCLCount( Numbers.Li(-1), 0, NumTypes.L0, 0); 703 END; 704 END DeleteAChar; 705 706 707 PROCEDURE NewLink(VAR oldptr : CARDINAL; curind : CARDINAL); 708 VAR 709 newline : LineType; 710 BEGIN 711 (*We don't have to check MaxLines here because NewLink is 712 only called in BumpWord, which we don't call if we're 713 close to the limit.*) 714 LowLevel.Fill( SYSTEM.ADR( newline), curind, blank); 715 StrEdit.SetLength( newline, curind); 716 GenLists.ListInsert( newline, GenLists.StrCode, TheList, oldptr + 1); 717 END NewLink; 718 719 720 PROCEDURE ReplaceWith(TheChr : CHAR); 721 VAR 722 LinesAdded, CharsAdded : INTEGER; 723 StartLine, CursorLine, CursorCol: CARDINAL; 724 RoomOnThisLine, BeyondEnd : BOOLEAN; 725 BEGIN 726 (* First we'll put the character into the list. Then we'll worry 727 about whether we have to wrap or scroll to display it. *) 728 CharsAdded := 0; 729 BeyondEnd := (TheNdx >= ListUtils.ElmtSize(TheList, TLine)); 730 IF BeyondEnd THEN 731 WHILE (TheNdx > ListUtils.ElmtSize(TheList, TLine)) DO 732 ListUtils.InsertIntoElmt( TheList, TLine, 733 SYSTEM.ADR(blank), 1, 65535 ); 734 (*pad with blanks out to TheNdx, if necessary*) 735 INC(CharsAdded); 736 END; 737 TCharCnt.longi := TCharCnt.longi - NumTypes.L2; 738 (*We do this to compensate for the fact that MoveAcrossTo 739 will think we've crossed over a CR/LF.*) 740 ListUtils.InsertIntoElmt( TheList, TLine, 741 SYSTEM.ADR(TheChr), 1, 65535 ); 742 (*append TheChr to the string at position TLine*) 743 INC(CharsAdded); 744 ELSE 745 IF Rec.overwriting THEN 746 ListUtils.OverwriteElmt( TheList, TLine, 747 SYSTEM.ADR(TheChr), 1, TheNdx ); 748 CharsAdded := 0; 749 ELSE 750 ListUtils.InsertIntoElmt( TheList, TLine, 751 SYSTEM.ADR(TheChr), 1, TheNdx ); 752 CharsAdded := 1; 753 END; 754 END; 755 756 RoomOnThisLine := (NOT Rec.Wrapping) OR 757 (ListUtils.ElmtSize(TheList, TLine) < MaxLength); 758 IF RoomOnThisLine THEN 759 MoveAcrossTo( TheNdx + 1 ); 760 WriteStrings( TLine, TheRow, TheRow ); 761 AddCLCount(Numbers.Li(CharsAdded), 0, NumTypes.L0, 0); 762 ELSE 763 StartLine := TLine; 764 CursorLine := TLine; 765 CursorCol := TheNdx; 766 ListUtils.ReformPara( TheList, 767 ListUtils.IndentationAt(TheList, TLine), MaxLength, StartLine, 768 CursorLine, CursorCol, LinesAdded, CharsAdded, TCharCnt.longi ); 769 AddCLCount( Numbers.Li(CharsAdded), LinesAdded, NumTypes.L0, 0 ); 770 MoveAcrossTo( 0 ); 771 (*Makes sure part of the current word isn't scrolled out of the 772 window. *) 773 MoveAcrossTo( CursorCol + 1 ); 774 MoveVerticallyTo( CursorLine ); 775 WriteStrings( TLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); 776 END; 777 END ReplaceWith; 778 779 780 PROCEDURE ScrollRegion( row1, row2 : CARDINAL; dist: INTEGER ); 781 VAR 782 NewTopLine: INTEGER; 783 BEGIN 784 NewTopLine := INTEGER(TLine - (TheRow - Rec.Row1)) + 785 INTEGER(row1 - Rec.Row1) + dist; 786 IF NOT VWindows.ScrollVertically( Rec.WindowHandle, 787 Rec.Col1, row1, Rec.Col2, row2, dist ) THEN 788 NewTopLine := Numbers.Min( NewTopLine, 1 ); 789 WriteStrings( NewTopLine, row1, row2 ); 790 RETURN; 791 END; 792 IF NewTopLine < 1 THEN 793 (*They want to move down by more lines than we have to fill with.*) 794 NewTopLine := 1 + ABS(dist); 795 INC( row1, CARDINAL(ABS(dist)) ); 796 END; 797 IF dist > 0 THEN 798 WriteStrings( CARDINAL(NewTopLine) + (row2 - row1) - 799 CARDINAL(dist), Rec.Row2 - CARDINAL(dist) + 1, 800 Rec.Row2 ); 801 ELSE 802 WriteStrings( CARDINAL(NewTopLine) + CARDINAL(ABS(dist)), 803 row1, CARDINAL(INTEGER(row1) + ABS(dist) - 1) ); 804 END; 805 END ScrollRegion; 806 807 808 PROCEDURE Reformat(); 809 VAR 810 LinesAdded, CharsAdded: INTEGER; 811 StartLine, CursorLine, CursorCol: CARDINAL; 812 BEGIN 813 StartLine := TLine; 814 CursorLine := TLine; 815 CursorCol := TheNdx; 816 ListUtils.ReformPara( TheList, 817 ListUtils.IndentationAt(TheList, StartLine), MaxLength, StartLine, 818 CursorLine, CursorCol, LinesAdded, CharsAdded, TCharCnt.longi ); 819 AddCLCount( Numbers.Li(CharsAdded), LinesAdded, NumTypes.L0, 0 ); 820 MoveAcrossTo( CursorCol ); 821 MoveVerticallyTo( CursorLine ); 822 WriteStrings( TLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); 823 END Reformat; 824 825 826 PROCEDURE InsertDeleteBuffer(); 827 VAR 828 BufLngth: CARDINAL; 829 CharsAdded, tmpl: LONGINT; 830 BEGIN 831 BufLngth := GenLists.ListLength( DeleteBuffer ); 832 IF BufLngth = 0 THEN 833 RETURN; 834 END; 835 ListUtils.InsertElmtsOf( DeleteBuffer, 1, BufLngth, 836 TheList, TLine ); 837 tmpl := ListUtils.CharCount( DeleteBuffer, 1, 65535 ); 838 IF tmpl > NumTypes.L65535 THEN 839 (*If they try to copy more than 64K at once, we throw 840 up our hands; the text gets inserted correctly, but 841 we don't bother to position the cursor after it. We 842 just go to the top and let them figure out where they 843 were.*) 844 RCharCnt.longi := RCharCnt.longi + tmpl; 845 RLineCnt := RLineCnt + BufLngth; 846 MoveVerticallyTo( 1 ); 847 MoveAcrossTo( 0 ); 848 CharsAdded := tmpl; 849 AddCLCount( CharsAdded, BufLngth, 850 NumTypes.L0, 0 ); 851 END; 852 CharsAdded := tmpl; 853 AddCLCount( CharsAdded, BufLngth, 854 NumTypes.L0, 0 ); 855 WriteStrings( TLine - 856 (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); 857 MoveVerticallyTo( TLine + BufLngth ); 858 END InsertDeleteBuffer; 859 860 PROCEDURE DeleteALine(); 861 VAR 862 delsize : INTEGER; 863 BEGIN 864 delsize := 2 + ListUtils.ElmtSize( TheList, TLine ); 865 IF TLine # LastLineDeleted THEN 866 IF GenLists.Initialized( DeleteBuffer ) THEN 867 GenLists.DisposeList( DeleteBuffer ); 868 END; 869 GenLists.NewList( DeleteBuffer ); 870 LastLineDeleted := TLine; 871 END; 872 ListUtils.InsertElmtsOf( TheList, TLine, 1, DeleteBuffer, 65535 ); 873 GenLists.ListDelete( TheList, TLine, 1); 874 IF TLine <= GenLists.ListLength( TheList) THEN 875 (*this isn't the last line*) 876 WriteStrings( TLine, TheRow, Rec.Row2 ); 877 AddCLCount( Numbers.Li(-delsize), -1, NumTypes.L0, 0); 878 ELSIF TLine # 1 THEN 879 (*this is the last line of many*) 880 VWindows.ClearPart( Rec.WindowHandle, Rec.Col1, 881 TheRow, Rec.Col2, TheRow); 882 AddCLCount( Numbers.Li(-delsize), -1, NumTypes.L0, 0); 883 MoveVerticallyTo( TLine - 1 ); 884 ELSE 885 (*This is the only line *) 886 GenLists.ListInsert( '', GenLists.StrCode, TheList, 1); 887 VWindows.ClearPart( Rec.WindowHandle, Rec.Col1, 888 TheRow, Rec.Col2, TheRow); 889 MoveAcrossTo( 0 ); 890 AddCLCount( Numbers.Li(2 - delsize), 0, 891 Numbers.Li(1 - INTEGER( TCharCnt.locard)), 0); 892 END; 893 END DeleteALine; 894 895 PROCEDURE JoinLines(); 896 (* joins this line to the previous one 897 (caused by a BSP in the first column or a del at the end) *) 898 VAR 899 addedtoend, firstleng : INTEGER; 900 tmpsize: CARDINAL; 901 tmpadr: SYSTEM.ADDRESS; 902 OnBlankLine : BOOLEAN; 903 BEGIN 904 IF TLine = 1 THEN 905 (* if this isn't the first line *) 906 RETURN; 907 END; 908 OnBlankLine := TheLength() = 0; 909 MoveAcrossTo( 0 ); 910 GenLists.GetElmtAdr( TheList, TLine - 1, tmpadr, tmpsize, DumType); 911 firstleng := ListUtils.ElmtSize( TheList, TLine - 1 ); 912 IF (firstleng # 0) AND (ByteFiddler.PeekChar(LowLevel.AddAddr(tmpadr, 913 firstleng - 1)) # blank[0]) THEN 914 (* if need a space at end of prior line to separate *) 915 ListUtils.InsertIntoElmt( TheList, TLine - 1, 916 SYSTEM.ADR(blank), 1, 65535 ); 917 (*append a blank to end of previous line*) 918 addedtoend := 1; 919 ELSE 920 addedtoend := 0; 921 END; 922 AddCLCount( Numbers.Li(addedtoend), 0, Numbers.Li(addedtoend), 0 ); 923 (*update char counts so that MoveTo procedures will count 924 correctly as line boundary is crossed.*) 925 MoveVerticallyTo( TLine - 1 ); 926 (*This changes TLine.*) 927 MoveAcrossTo( TheLength() ); 928 IF NOT OnBlankLine THEN 929 GenLists.GetElmtAdr( TheList, TLine + 1, tmpadr, 930 tmpsize, DumType ); 931 ListUtils.InsertIntoElmt( TheList, TLine, tmpadr, 932 tmpsize, 65535 ); 933 AddCLCount( -NumTypes.L2, -1, -NumTypes.L2, 0 ); 934 (*account for deletion of CR/LF and TLine*) 935 ELSE 936 AddCLCount( -NumTypes.L2, -1, NumTypes.L0, 0 ); 937 (*We've lost a line, but we're past the CR/LF 938 on the line above*) 939 END; 940 GenLists.ListDelete( TheList, TLine + 1, 1); 941 WriteStrings( TLine, TheRow, TheRow ); 942 ScrollRegion( TheRow + 1, Rec.Row2, 1 ); 943 END JoinLines; 944 945 946 PROCEDURE NewLine(); 947 VAR 948 prvadr: SYSTEM.ADDRESS; 949 OldNdx, prvsize : CARDINAL; 950 BEGIN 951 IF NOT CheckMax() THEN 952 RETURN; 953 END; 954 OldNdx := TheNdx; 955 MoveAcrossTo( 0 ); 956 GenLists.GetElmtAdr( TheList, TLine, prvadr, prvsize, DumType); 957 prvsize := ListUtils.ElmtSize( TheList, TLine ); 958 (*Reduces prvsize to number of bytes before the 0C.*) 959 GenLists.ListInsert( '', GenLists.StrCode, TheList, TLine + 1 ); 960 IF OldNdx = 0 THEN 961 AddCLCount( NumTypes.L2, 1, NumTypes.L2, 0 ); 962 (*Increment char total for the new CR/LF, and increment the 963 char position because MoveVerticallyTo won't count the 964 trailing CR/LF in this case--it thinks we've already 965 skipped it.*) 966 ELSE 967 AddCLCount( NumTypes.L2, 1, NumTypes.L0, 0 ); 968 (*Increment char total for the new CR/LF.*) 969 END; 970 IF OldNdx < prvsize THEN 971 ListUtils.InsertIntoElmt( TheList, TLine + 1, 972 LowLevel.AddAddr(prvadr, OldNdx), prvsize - OldNdx, 0 ); 973 ByteFiddler.PokeChar( 0C, LowLevel.AddAddr(prvadr, OldNdx) ); 974 END; 975 WriteStrings( TLine, TheRow, TheRow ); 976 IF TheRow < Rec.Row2 THEN 977 ScrollRegion( TheRow + 1, Rec.Row2, -1 ); 978 END; 979 MoveVerticallyTo( TLine + 1 ); 980 END NewLine; 981 982 983 PROCEDURE NextWord(); 984 VAR 985 tmpcol, leng : INTEGER; 986 tmpsize: CARDINAL; 987 txtadr, tmpadr: SYSTEM.ADDRESS; 988 BEGIN 989 leng := ListUtils.ElmtSize( TheList, TLine ); 990 IF TheNdx + 1 >= CARDINAL(leng) THEN 991 MoveVerticallyTo( TLine + 1 ); 992 GenLists.GetElmtAdr( TheList, TLine, txtadr, tmpsize, DumType); 993 MoveAcrossTo(0); 994 IF ByteFiddler.PeekChar(txtadr) # blank[0] THEN 995 RETURN; 996 END; 997 END; 998 GenLists.GetElmtAdr( TheList, TLine, txtadr, tmpsize, DumType); 999 tmpcol := TheNdx; 1000 LOOP 1001 tmpadr := LowLevel.AddAddr( txtadr, tmpcol ); 1002 IF tmpcol + 1 < leng THEN 1003 IF ByteFiddler.PeekChar(tmpadr) = blank[0] THEN 1004 LowLevel.IncAddr( tmpadr, 1 ); 1005 dumint := LowLevel.ScanNE(leng - tmpcol - 1, blank, tmpadr); 1006 MoveAcrossTo(tmpcol + 1 + dumint); 1007 RETURN; 1008 ELSE 1009 INC(tmpcol); 1010 END; 1011 ELSE 1012 MoveAcrossTo(leng); 1013 RETURN; 1014 END; 1015 END; 1016 END NextWord; 1017 1018 PROCEDURE LastWord(); 1019 VAR 1020 tmpcol : INTEGER; 1021 tmpsize: CARDINAL; 1022 txtadr, tmpadr: SYSTEM.ADDRESS; 1023 BEGIN 1024 tmpcol := TheNdx; 1025 GenLists.GetElmtAdr( TheList, TLine, txtadr, tmpsize, DumType); 1026 LOOP 1027 IF tmpcol > 0 THEN 1028 tmpadr := LowLevel.AddAddr(txtadr, tmpcol - 1); 1029 IF ByteFiddler.PeekChar(tmpadr) # blank[0] THEN 1030 dumint := LowLevel.ScanEQ(-tmpcol,blank,tmpadr); 1031 (* last is + since scan returns neg.*) 1032 MoveAcrossTo( tmpcol + dumint); 1033 EXIT; 1034 ELSE 1035 DEC( tmpcol); 1036 END; 1037 ELSE 1038 MoveVerticallyTo( TLine - 1 ); 1039 MoveAcrossTo( TheLength() ); 1040 EXIT; 1041 END; 1042 END; 1043 END LastWord; 1044 1045 PROCEDURE KeyResponse(); 1046 VAR 1047 OvrStr : ARRAY [0..10] OF CHAR; 1048 SavedFore, SavedBack : MsColors.AColor; 1049 SavedAttr : MsColors.AMonoAttribute; 1050 BEGIN 1051 LOOP 1052 Rec.EdLastKey := KbdInput.KeyHit( KbdInput.AnyKeyNum ); 1053 IF Rec.FrameRec # NIL THEN 1054 UpdateFrameRec(); 1055 UserOps.TheKeyHandler( Rec.FrameRec, Rec.EdLastKey, Rec.NextFrame ); 1056 IF Rec.overwriting THEN 1057 VWindows.SetCursorHeight( Rec.WindowHandle, 2); 1058 ELSE 1059 VWindows.SetCursorHeight( Rec.WindowHandle, 4); 1060 END; 1061 SetAttribOrColor( Rec.EntryForeColor, Rec.EntryBackColor, 1062 Rec.EntryAttrib ); 1063 GetFrameRecData(); 1064 END; 1065 IF (Rec.EdLastKey = UserOps.SubmitKey) 1066 OR (Rec.EdLastKey = UserOps.BackupKey) 1067 OR (Rec.EdLastKey = UserOps.ExitKey) THEN 1068 EXIT; 1069 END; 1070 CASE Rec.EdLastKey OF 1071 Key.Up : (*up arrow*) 1072 IF (TLine = 1) AND 1073 BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN 1074 (*We're letting the user exit from the editor 1075 window by pressing the up arrow on the top line 1076 of the file.*) 1077 EXIT; 1078 ELSE 1079 MoveVerticallyTo( TLine - 1 ); 1080 END; 1081 | Key.Down : (*down arrow*) 1082 IF (TLine = GenLists.ListLength(TheList)) AND 1083 BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN 1084 (*We're letting the user exit from the editor 1085 window by pressing the down arrow on the 1086 bottom line of the file.*) 1087 EXIT; 1088 ELSE 1089 MoveVerticallyTo( TLine + 1 ); 1090 END; 1091 | Key.Left: (*left arrow*) 1092 IF TheNdx>0 THEN 1093 MoveAcrossTo(TheNdx - 1); 1094 ELSIF BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN 1095 (*We're letting the user exit from the editor 1096 window by pressing the left arrow on the 1097 left edge of the window.*) 1098 EXIT; 1099 ELSIF (TheRow # Rec.Row1) THEN 1100 MoveVerticallyTo( TLine - 1 ); 1101 MoveAcrossTo( TheLength()); 1102 END; 1103 | Key.Right: (*right arrow*) 1104 IF TheNdx < TheLength() THEN 1105 MoveAcrossTo( TheNdx + 1); 1106 ELSIF BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN 1107 (*We're letting the user exit from the editor 1108 window by pressing the right arrow at the end 1109 of the current line.*) 1110 EXIT; 1111 ELSIF (TLine # GenLists.ListLength( TheList)) THEN 1112 MoveVerticallyTo( TLine + 1 ); 1113 MoveAcrossTo(0); 1114 END; 1115 | Key.Tab, Key.CtrlRight: (*Tab and Ctrl-RightArrow*) 1116 IF TheNdx < TheLength() THEN 1117 NextWord(); 1118 ELSIF BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN 1119 (*We're letting the user exit from the editor 1120 window by pressing the Tab or Ctrl-RightArrow if 1121 they're in the FieldExitKeySet.*) 1122 EXIT; 1123 ELSE 1124 NextWord(); 1125 END; 1126 | Key.BackTab, Key.CtrlLeft: (*BackTab and Ctrl-LeftArrow*) 1127 IF TheNdx>0 THEN 1128 LastWord(); 1129 ELSIF BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN 1130 EXIT; 1131 ELSE 1132 LastWord(); 1133 END; 1134 | Key.F4 : 1135 NextWord(); 1136 | Key.Ins : 1137 IF NOT Rec.ReadOnly THEN 1138 Rec.overwriting := NOT Rec.overwriting; 1139 IF Rec.overwriting THEN 1140 VWindows.SetCursorHeight( Rec.WindowHandle, 2 ); 1141 ELSE 1142 VWindows.SetCursorHeight( Rec.WindowHandle, 4 ); 1143 END; 1144 IF Rec.FrameRec # NIL THEN 1145 SavedFore := VWindows.ForeColor( Rec.WindowHandle ); 1146 SavedBack := VWindows.BackColor( Rec.WindowHandle ); 1147 SavedAttr := VWindows.MonoAttr( Rec.WindowHandle ); 1148 SetPromptColors( Rec.FrameRec ); 1149 END; 1150 IF Rec.DoCounting THEN 1151 OvrOrIns( OvrStr); 1152 VWindows.DrawStr( Rec.WindowHandle, 71, Rec.CountRow, 1153 SYSTEM.ADR(OvrStr), M2Strings.Length(OvrStr) ); 1154 END; 1155 IF Rec.FrameRec # NIL THEN 1156 VWindows.SetForeColor( Rec.WindowHandle, SavedFore ); 1157 VWindows.SetBackColor( Rec.WindowHandle, SavedBack ); 1158 VWindows.SetMonoAttr( Rec.WindowHandle, SavedAttr ); 1159 END; 1160 VWindows.GotoXY( Rec.WindowHandle, 1161 Rec.Col1 + TheNdx - ColsScrolled, TheRow); 1162 END; 1163 | Key.Del : 1164 IF NOT Rec.ReadOnly THEN 1165 Rec.ChangeMade := TRUE; 1166 IF TheNdx < TheLength() THEN 1167 DeleteAChar(0); 1168 ELSE 1169 MoveVerticallyTo( TLine + 1 ); 1170 MoveAcrossTo( 0 ); 1171 JoinLines(); 1172 END; 1173 END; 1174 | Key.Home: 1175 (* go to start of current line*) 1176 MoveAcrossTo(0); 1177 | Key.AltD : 1178 IF NOT Rec.ReadOnly THEN 1179 Rec.ChangeMade := TRUE; 1180 DeleteALine(); 1181 END; 1182 | Key.AltI, Key.AltU : 1183 IF NOT Rec.ReadOnly THEN 1184 Rec.ChangeMade := TRUE; 1185 InsertDeleteBuffer(); 1186 END; 1187 | Key.End: (*End*) 1188 (* go to end of current line*) 1189 MoveAcrossTo( TheLength()); 1190 | Key.PgUp: (*PgUp*) 1191 IF (TLine = 1) AND 1192 BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN 1193 (*We're letting the user exit from the editor 1194 window by pressing PgUp on the top line 1195 of the file.*) 1196 EXIT; 1197 ELSE 1198 PageUp(); 1199 (* go up one page *) 1200 END; 1201 | Key.PgDn: (*PgDn*) 1202 IF (TLine = GenLists.ListLength(TheList)) AND 1203 BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN 1204 (*We're letting the user exit from the editor 1205 window by pressing the PgDn key on the 1206 bottom line of the file.*) 1207 EXIT; 1208 ELSE 1209 PageDown(); 1210 (* go down one page *) 1211 END; 1212 | Key.CtrlPgUp: 1213 (* go to top of file *) 1214 MoveVerticallyTo( 1 ); 1215 | Key.CtrlPgDn: 1216 (* go to end of text file *) 1217 MoveVerticallyTo( GenLists.ListLength(TheList) ); 1218 MoveAcrossTo( TheLength() ); 1219 | Key.F7: 1220 (* pack paragraphs starting at current line and going 1221 down until indentation changes *) 1222 IF (Rec.Wrapping) AND (NOT Rec.ReadOnly) THEN 1223 Rec.ChangeMade := TRUE; 1224 Reformat(); 1225 END; 1226 | Key.F7 + Key.FShift: 1227 (*ShiftF7 toggles between wrapping and not wrapping.*) 1228 Rec.Wrapping := NOT Rec.Wrapping; 1229 IF Rec.Wrapping AND (NOT Rec.ReadOnly) THEN 1230 Rec.ChangeMade := TRUE; 1231 Reformat(); 1232 END; 1233 | Key.F8: 1234 Testing := NOT Testing; 1235 | Key.BackSpace : 1236 IF NOT Rec.ReadOnly THEN 1237 Rec.ChangeMade := TRUE; 1238 IF TheNdx>0 THEN 1239 DeleteAChar(1); 1240 ELSE 1241 JoinLines(); 1242 END; 1243 END; 1244 | Key.Return : 1245 IF NOT Rec.ReadOnly THEN 1246 Rec.ChangeMade := TRUE; 1247 NewLine(); 1248 END; 1249 ELSE 1250 IF (NOT Rec.ReadOnly) AND (Rec.EdLastKey # 0) 1251 AND (Rec.EdLastKey < KbdInput.Extended) THEN 1252 Rec.ChangeMade := TRUE; 1253 ReplaceWith( CHR(Rec.EdLastKey) ); 1254 END; 1255 END; 1256 END; 1257 END KeyResponse; 1258 1259 VAR 1260 SavedHeight, BxCol1, BxCol2, BxRow1, BxRow2 : CARDINAL; 1261 1262 BEGIN (*DefaultEditor*) 1263 GetFrameRecData(); 1264 Rec.ChangeMade := FALSE; 1265 IF Rec.Col2 < Rec.Col1 THEN 1266 INC(Rec.Col2, Rec.Col1); 1267 END; 1268 ColsScrolled := 0; 1269 LastLineDeleted := 0; 1270 Rec.Col1 := Numbers.Between(1, Rec.Col1, DisplayLeng); 1271 Rec.Row1 := Numbers.Between(1, Rec.Row1, Rec.Row2); 1272 Rec.Row2 := Numbers.Between(Rec.Row1, Rec.Row2, 1273 VWindows.EndRow(Rec.WindowHandle)); 1274 Rec.Col2 := Numbers.Between(Rec.Col1, Rec.Col2, DisplayLeng); 1275 BxCol1 := Rec.Col1; 1276 BxCol2 := Rec.Col2; 1277 BxRow1 := Rec.Row1; 1278 BxRow2 := Rec.Row2; 1279 IF Rec.FrameRec # NIL THEN 1280 SavedHeight := VWindows.GetCursorHeight( Rec.FrameRec^.WindowHandle ); 1281 END; 1282 SetAttribOrColor( Rec.EntryForeBox, Rec.EntryBackBox, Rec.EntryAttrib ); 1283 CASE Rec.EntryBox OF 1284 (* Draw Entry Box *) 1285 2: 1286 VWindows.DrawBox( Rec.WindowHandle, 1287 VWindows.DoubleBox, Rec.Col1, Rec.Row1, Rec.Col2, 1288 Rec.Row2); 1289 | 1: 1290 VWindows.DrawBox( Rec.WindowHandle, 1291 VWindows.SingleBox, Rec.Col1, Rec.Row1, Rec.Col2, 1292 Rec.Row2); 1293 ELSE (*do nothing*); 1294 END; 1295 IF (Rec.EntryBox # 0) OR (Rec.ExitBox # 0) THEN 1296 (* Correct coordinates to the area inside the box *) 1297 INC(Rec.Col1); 1298 INC(Rec.Row1); 1299 DEC(Rec.Row2); 1300 DEC(Rec.Col2); 1301 END; 1302 IF Rec.DoCounting AND (Rec.Row2 >= Rec.CountRow) THEN 1303 Rec.Row2 := Numbers.Min( Rec.Row2, Rec.CountRow - 1 ); 1304 (*This makes sure Row2 doesn't interfere with the 1305 prompt line.*) 1306 END; 1307 WindowHeight := Rec.Row2 - Rec.Row1 + 1; 1308 Rec.TextRow1 := Numbers.Between(1, Rec.TextRow1, 1309 GenLists.ListLength(TheList)); 1310 Rec.CursorCol := Numbers.Between(1, Rec.CursorCol, 1311 (Rec.Col2 - Rec.Col1) + 1 ); 1312 Rec.CursorRow := Numbers.Between(1, Rec.CursorRow, 1313 WindowHeight ); 1314 Rec.CursorRow := Numbers.Between(1, Rec.CursorRow, 1315 GenLists.ListLength(TheList) + 1 - Rec.TextRow1 ); 1316 (*We correct Rec.CursorRow again to prevent it from falling 1317 below the bottom of TheList. Added 16 Nov 86.*) 1318 SetAttribOrColor( Rec.EntryForeColor, Rec.EntryBackColor, 1319 Rec.EntryAttrib ); 1320 MaxLength := (Rec.Col2 - Rec.Col1) + 1; 1321 LowLevel.Fill( SYSTEM.ADR(BlankStr), DisplayLeng + 1, blank); 1322 Testing := FALSE; 1323 IF GenLists.ListLength( TheList) # 0 THEN 1324 WriteStrings( Rec.TextRow1, Rec.Row1, Rec.Row2); 1325 TLine := Rec.TextRow1 + Rec.CursorRow - 1; 1326 ELSE 1327 (* set counter to line one and clear window *) 1328 GenLists.ListInsert( '', GenLists.StrCode, TheList, 1); 1329 TLine := 1; 1330 VWindows.ClearPart( Rec.WindowHandle, Rec.Col1, 1331 Rec.Row1, Rec.Col2, Rec.Row2); 1332 END; 1333 TheRow := Rec.CursorRow + Rec.Row1 - 1; 1334 TheNdx := Rec.CursorCol - 1; 1335 CountChars( 1, RCharCnt.longi, RLineCnt, TLine, TCharCnt.longi); 1336 TCharCnt.longi := TCharCnt.longi + Numbers.Lc( TheNdx ); 1337 IF Rec.DoCounting THEN 1338 WriteFooter(); 1339 ELSE 1340 RCharCnt.longi := NumTypes.L1; 1341 RLineCnt := 1; 1342 TCharCnt.longi := NumTypes.L1; 1343 END; 1344 VWindows.GotoXY( Rec.WindowHandle, Rec.Col1 + 1345 TheNdx - ColsScrolled, TheRow); 1346 IF Rec.overwriting THEN 1347 VWindows.SetCursorHeight( Rec.WindowHandle, 2); 1348 ELSE 1349 VWindows.SetCursorHeight( Rec.WindowHandle, 4); 1350 END; 1351 KeyResponse(); 1352 Rec.CursorRow := (TheRow + 1) - Rec.Row1; 1353 Rec.CursorCol := 1 + TheNdx; 1354 Rec.TextRow1 := TLine + 1 - Rec.CursorRow; 1355 DoExitBox := ( Rec.ExitBox # Rec.EntryBox) OR 1356 ( Rec.ExitForeBox # Rec.EntryForeBox) OR 1357 ( Rec.ExitBackBox # Rec.EntryBackBox) OR 1358 ( Rec.ExitAttrib # Rec.EntryAttrib); 1359 (* whether the exit box differs from the entry, and so must 1360 be re-drawn *) 1361 IF DoExitBox THEN 1362 SetAttribOrColor( Rec.ExitForeBox, Rec.ExitBackBox, Rec.ExitAttrib ); 1363 CASE Rec.ExitBox OF 1364 2: 1365 VWindows.DrawBox( Rec.WindowHandle, 1366 VWindows.DoubleBox, BxCol1, BxRow1, BxCol2, 1367 BxRow2); 1368 | 1: 1369 VWindows.DrawBox( Rec.WindowHandle, 1370 VWindows.SingleBox, BxCol1, BxRow1, BxCol2, 1371 BxRow2); 1372 ELSE 1373 VWindows.ClearPart( Rec.WindowHandle, 1374 BxCol1, BxRow1, BxCol2, BxRow2); 1375 END; 1376 END; 1377 SetAttribOrColor( Rec.ExitForeColor, Rec.ExitBackColor, 1378 Rec.ExitAttrib ); 1379 IF (Rec.EntryForeColor # Rec.ExitForeColor) OR 1380 (Rec.EntryBackColor # Rec.ExitBackColor) OR 1381 (Rec.EntryAttrib # Rec.ExitAttrib) OR 1382 (DoExitBox AND ( Rec.ExitBox = 0)) THEN 1383 WriteStrings( TLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); 1384 (* Rewrite the current screen *) 1385 END; 1386 IF (Rec.EntryBox # 0) OR (Rec.ExitBox # 0) THEN 1387 (* Set coordinates back to area that includes box *) 1388 DEC(Rec.Col1); 1389 DEC(Rec.Row1); 1390 INC(Rec.Row2); 1391 INC(Rec.Col2); 1392 END; 1393 UpdateFrameRec(); 1394 IF Rec.FrameRec # NIL THEN 1395 VWindows.SetCursorHeight( Rec.FrameRec^.WindowHandle, SavedHeight ); 1396 END; 1397 END DefaultEditor; 1398 1399 1400 PROCEDURE SetGlobals( VAR Rec: VEditor.AnEdControlRec ); 1401 BEGIN 1402 overwriting := Rec.overwriting; 1403 DoCounting := Rec.DoCounting; 1404 MaxLines := Rec.MaxLines; 1405 EdLastKey := Rec.EdLastKey; 1406 ExitBox := Rec.ExitBox; 1407 EntryBox := Rec.EntryBox; 1408 CountRow := Rec.CountRow; 1409 EdPromptFore := Rec.EdPromptFore; 1410 EdPromptBack := Rec.EdPromptBack; 1411 EdPromptAttrib := Rec.EdPromptAttrib; 1412 EntryAttrib := Rec.EntryAttrib; 1413 ExitAttrib := Rec.ExitAttrib; 1414 EntryForeColor := Rec.EntryForeColor; 1415 EntryBackColor := Rec.EntryBackColor; 1416 ExitForeColor := Rec.ExitForeColor; 1417 ExitBackColor := Rec.ExitBackColor; 1418 EntryForeBox := Rec.EntryForeBox; 1419 EntryBackBox := Rec.EntryBackBox; 1420 ExitForeBox := Rec.ExitForeBox; 1421 ExitBackBox := Rec.ExitBackBox; 1422 END SetGlobals; 1423 1424 1425 PROCEDURE GetGlobals( VAR Rec: VEditor.AnEdControlRec ); 1426 BEGIN 1427 Rec.overwriting := overwriting; 1428 Rec.DoCounting := DoCounting; 1429 Rec.MaxLines := MaxLines; 1430 Rec.ExitBox := ExitBox; 1431 Rec.EntryBox := EntryBox; 1432 Rec.CountRow := CountRow; 1433 Rec.EdPromptFore := EdPromptFore; 1434 Rec.EdPromptBack := EdPromptBack; 1435 Rec.EdPromptAttrib := EdPromptAttrib; 1436 Rec.EntryAttrib := EntryAttrib; 1437 Rec.ExitAttrib := ExitAttrib; 1438 Rec.EntryForeColor := EntryForeColor; 1439 Rec.EntryBackColor := EntryBackColor; 1440 Rec.ExitForeColor := ExitForeColor; 1441 Rec.ExitBackColor := ExitBackColor; 1442 Rec.EntryForeBox := EntryForeBox; 1443 Rec.EntryBackBox := EntryBackBox; 1444 Rec.ExitForeBox := ExitForeBox; 1445 Rec.ExitBackBox := ExitBackBox; 1446 END GetGlobals; 1447 1448 VAR 1449 GlobalEdRec: VEditor.AnEdControlRec; 1450 1451 PROCEDURE ScrnEdit(Col1, Row1, Col2, Row2 : CARDINAL; 1452 VAR TheList : GenLists.GenList; VAR TextRow1, CursorCol, 1453 CursorRow: CARDINAL; VAR ChangeMade: BOOLEAN; 1454 ReadOnly: BOOLEAN; VAR FrameRec: ScrnTypes.DisplayFrame): INTEGER; 1455 VAR 1456 LocalRec : VEditor.AnEdControlRec; 1457 tmpint: INTEGER; 1458 BEGIN 1459 VEditor.InitEdRec( LocalRec ); 1460 GetGlobals( LocalRec ); 1461 LocalRec.Wrapping := FALSE; 1462 LocalRec.NextFrame := ''; 1463 LocalRec.Col1 := Col1; 1464 LocalRec.Row1 := Row1; 1465 LocalRec.Col2 := Col2; 1466 LocalRec.Row2 := Row2; 1467 LocalRec.TextRow1 := TextRow1; 1468 LocalRec.CursorCol := CursorCol; 1469 LocalRec.CursorRow := CursorRow; 1470 LocalRec.ChangeMade := ChangeMade; 1471 LocalRec.ReadOnly := ReadOnly; 1472 LocalRec.FrameRec := FrameRec; 1473 DefaultEditor( TheList, LocalRec ); 1474 TextRow1 := LocalRec.TextRow1; 1475 CursorCol := LocalRec.CursorCol; 1476 CursorRow := LocalRec.CursorRow; 1477 ChangeMade := LocalRec.ChangeMade; 1478 IF StrConv.StrToInteger( LocalRec.NextFrame, 0, tmpint ) THEN 1479 RETURN tmpint; 1480 ELSE 1481 RETURN 0; 1482 END; 1483 END ScrnEdit; 1484 1485 PROCEDURE Init(); 1486 BEGIN 1487 IF Initialized THEN 1488 RETURN; 1489 ELSE 1490 Initialized := TRUE; 1491 END; 1492 (*EntryDiag: 1493 Diagnostics.Init(); 1494 :EntryDiag*) 1495 1496 BigSets.Init(); 1497 ByteFiddler.Init(); 1498 GenLists.Init(); 1499 KbdInput.Init(); 1500 Key.Init(); 1501 ListUtils.Init(); 1502 LowLevel.Init(); 1503 M2Strings.Init(); 1504 MsColors.Init(); 1505 Numbers.Init(); 1506 NumTypes.Init(); 1507 PosUtils.Init(); 1508 ScrnTypes.Init(); 1509 ScrnUtl1.Init(); 1510 Spkr.Init(); 1511 StrConv.Init(); 1512 StrEdit.Init(); 1513 UserOps.Init(); 1514 VEditor.Init(); 1515 VWindows.Init(); 1516 (*EntryDiag: 1517 Diagnostics.diagS( 'Entering Editor', '' ); 1518 :EntryDiag*) 1519 1520 VEditor.InitEdRec( GlobalEdRec ); 1521 SetGlobals( GlobalEdRec ); 1522 blank[0] := ' '; 1523 GenLists.NilList( DeleteBuffer ); 1524 1525 (*EntryDiag: 1526 Diagnostics.diagS( 'Exiting Editor', '' ); 1527 :EntryDiag*) 1528 END Init; 1529 1530 BEGIN 1531 Initialized := FALSE; 1532 Init(); 1533 END Editor. 4 errors