defaria@hpclapd.HP.COM (Andy DeFaria) (01/03/91)
I have been playing around with my mouse and I have gotten a mouse unit that let's me track mouse events and the like. What I'm trying to do now is implement a cut and paste procedure so that a button 1 drag will highlight text on the screen and place the text into a cut buffer. Button 2 will paste any text. This is turning out to be difficult and I would appreciate any help that I can get. One of the problems that I have is that there can be up to 2000 characters cut and TP only likes strings < 256 characters. Another problem is that currently my highlight and cut procedure isn't smart enough to be able to cut only what is highlighted and tends to cut the same character(s) multiple times. I know that given more time, debugging and coding I could work through it but I would appreciate any pointers (and/or code) to help me complete this task. Thanks in advance.
CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) (01/07/91)
In article <950048@hpclapd.HP.COM>, defaria@hpclapd.hp.com (Andy DeFaria) wrote: [...deleted...] >One of the problems that I have is that there can be up to 2000 >characters cut and TP only likes strings < 256 characters. >Another problem is that currently my highlight and cut procedure >isn't smart enough to be able to cut only what is highlighted >and tends to cut the same character(s) multiple times. I know >that given more time, debugging and coding I could work through it >but I would appreciate any pointers (and/or code) to help me >complete this task. Don't cut to a string: cut to an array of char (or byte or word). (Be sure to note that the simplest cut (a Move from screen memory to your array) will pick up the attribute bytes as well as the character bytes.) The array will not be limited to 255 char. When pasting, you will have to consider issues related to blanks at the end of lines (if you are cutting a rectangle from the screen, and some lines in it are shorter than others, like text with a ragged right margin) and implicit carriage returns (when text runs all the way to the right margin), etc. As for the cutting of characters multiple times, I don't think we can really give you a clue where you're going wrong without seeing some code. Perhaps your drag algorithm is off? It seems to me that you should be picking off an upper left corner and a lower right corner (begin and end of the drag), then doing some kind of action that boils down to i := 0; for y := ytl to ylr do for x := xtl to xlr do begin buffer[i] := charAt(x,y); Inc(i); end; (where you've got an appropriate charAt function). +--------------------------------------------------------------------+ | Karl Brendel Centers for Disease Control | | Internet: CDCKAB@EMUVM1.BITNET Epidemiology Program Office | | Bitnet: CDCKAB@EMUVM1 Atlanta, GA, USA | | Home of Epi Info 5.0 | +--------------------------------------------------------------------+
defaria@hpclapd.HP.COM (Andy DeFaria) (01/08/91)
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 }