Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!samsung!dali.cs.montana.edu!uakari.primate.wisc.edu!zaphod.mps.ohio-state.edu!swrinde!elroy.jpl.nasa.gov!sdd.hp.com!hplabs!hpda!hpcuhb!hpcllla!hpclisp!defaria@hpclapd.HP.COM From: defaria@hpclapd.HP.COM (Andy DeFaria) Newsgroups: comp.lang.pascal Subject: Re: Looking for a cut/paste procedure Message-ID: <950051@hpclapd.HP.COM> Date: 7 Jan 91 19:26:17 GMT References: <950048@hpclapd.HP.COM> Organization: Hewlett-Packard Calif. Language Lab Lines: 149 I have cutting working now, however I still have problems with highlighting selected text: My problems are not with actually cutting the text from the screen buffer itself but more highlighting the text that is to be cut in a smooth interactive fashion. It is not as easy as you might imagine. Roughly you need to mark where selection begins (CutRegion). Then as the pointer moves you want to highlight the selected region. Plus you may need to unhighlight some region (think of the pointer moving backward). Brute force algorithm of unhighlighting all of the previous region and re-highlighting the new region produces flicker as the update of the display is not that fast or optimized so the following algorithm attempts to highlight (and unhighlight) only that which is necessary. You must also take into consideration when the pointer has moved up or down a row and the highlighting that needs to be done. This is sort of handled when I finally figured out that it would be better to think of video memory as a one dimensional array of characters instead of a two dimensional array of rows and columns. Still my HighlightText routine does not handle things accurately. Another problem is that mouse events are not always reported. You may get an mouse event that says the mouse has moved to pixel (120, 80) (screen position 15, 10) and its prior position was pixel (80, 80) (screen position 10, 10). This in and of itself is not difficult to handle but picture this: You have a ten character block currently selected (row 10 column 10 thru row 10 column 20) and you get a mouse event that says the mouse has moved to row 10 column 15. You cannot unhighlight the proper region unless you know which *direction* that mouse moved from. (i.e. did it go from 10, 10 to 10, 15 or from 10, 20?). I think that this can easily be solved by keeping track of the last known pointer position but it was at this point that I said "Boy, this is starting to get difficult. And all this code to execute for a mouse interrupt! Maybe I'm just going about this the wrong way?" and decided to ask the net. Here is an excerpt of my code: { HighlightText: Highlights text from CutRegion to NewStop. Main problems are } { are here. This procedure does not always highlight the text } { properly. Consider when NewStop goes < CutRegion.Start } Procedure HighlightText (NewStop : Integer); Var I : Integer; Begin If NewStop > CutRegion.Stop then Begin For I := CutRegion.Stop to NewStop do ScreenAddress^.Position [I].Attribute := (Red Shl 4) + Black; CutRegion.Stop := NewStop; End else If NewStop < CutRegion.Start then Begin For I := CutRegion.Start to NewStop do ScreenAddress^.Position [I].Attribute := (Red Shl 4) + Black; CutRegion.Start := NewStop; End else Begin For I := NewStop to CutRegion.Stop do ScreenAddress^.Position [I].Attribute := (Black Shl 4) + LightGray; CutRegion.Stop := NewStop; End; End; { CutText : This interrupt procedure is called by the mouse driver whenever } { Mouse events occur. It will handle LeftDown (start cut), LeftUp } { (end cur), move while LeftDown (select and highlight text) and } { RightDown (paiste). } {$F+} Procedure CutText (Flags, CS, IP, AX, BX,CX,DX,SE, DI, DS, ES, BP : Word); Interrupt; Var NewStop : Integer; I : Integer; Begin If AX = LeftDown then Begin { Unhighlight any old CutRegion } For I := CutRegion.Start to CutRegion.Stop do ScreenAddress^.Position [I].Attribute := (Black Shl 4) + LightGray; { Set Start and Stop to current character. Note formula converts the } { pixel offsets in DX and CX to an offset from the beginning of video } { memory. } CutRegion.Start := (DX * 10) + (CX div 8) + 1; CutRegion.Stop := CutRegion.Start; SetLength (CutBuffer, 0); End else If AX = LeftUp then Begin { Turn off pointer and cut the CutRegion. Note that } { CutBuffer is defined as a BigString and ConCat will add } { a character to the end of a BigString. } DisplayPointer (False); For I := CutRegion.Start to CutRegion.Stop do ConCat (CutBuffer, ScreenAddress^.Position [I].Character); End else If AX = RightDown then Begin { Dumb paiste routine for now. Simply write CutBuffer on line 25. } GotoXY (1, 25); ClrEOL; Write ('CutBuffer: '); PrintBigString (Output, CutBuffer); End else If AX = Move then Begin DisplayPointer (True); { Turn on pointer on movement. } If ButtonType (BX) = Button1 then Begin { Button 1 drag } NewStop := (DX * 10) + (CX div 8) + 1; { Events are generated for every pixel so we check to see if we have } { left the current character. At last count that was CutRegion.Stop. } { So if the NewStop is <> CutRegion.Stop then it must have moved out- } { the last character position and we need to HighlightText. } If NewStop <> CutRegion.Stop then HighlightText (NewStop); End; End; {------------------------------------------------------------------------------} { This inline code will pop all registers off the stack and then does a "far" } { return. This is useful in interrupt procedures that need to do a far return } { instead of executing jthe IRET that Turbo Pascal inserts for all Interrupt } { procedures. } {------------------------------------------------------------------------------} Inline ($8B/$E5/ $5D/ $07/ $1F/ $5F/ $5E/ $5A/ $59/ $5B/ $58/$CB); End; { EnableCutText: Simply sets mouse interrupt handler to CutText } Procedure EnableCutText; Begin { EnableCutText } If Not MousePresent then Exit; EnableEvents (@CutText, LeftDown + LeftUp + Move + RightDown); End; { EnableCutText }