ðáSyntax10.Scn.FntSyntax10i.Scn.FntÅ ƒyñSyntax10b.Scn.FntÀ¦¹QZ#;MODULE Clipboard; (* MH 3.12.93; based on a semester project by A. Hendseth and M. H„lzel *) (* CS, 9.11.95, copy elements and fonts within Oberon, "Clipboard.Snapshot drag" for selecting any part of the display *) IMPORT S := SYSTEM, ShowError, Win32, Display, Texts, Viewers, TextFrames, Oberon, In, Input, C := Console; CONST NULL = 0; CFText = 1; CFBitmap = 2; VAR W: Texts.Writer; oberonClipboard: Texts.Buffer; PROCEDURE PutToClipboard (T: Texts.Text; beg, end: LONGINT); CONST GmemDDEShare = 02000H; GmemMoveable = 2H; VAR R: Texts.Reader; ch: CHAR; h, data, size, adr: LONGINT; done: BOOLEAN; BEGIN done := Win32.OpenClipboard(Win32.Display); IF done THEN Texts.OpenReader(R, T, beg); size := 0; WHILE Texts.Pos(R) < end DO Texts.Read(R, ch); IF ch = 0DX THEN INC(size, 2) ELSE INC(size) END ; END ; Win32.EmptyClipboard; h := Win32.GlobalAlloc(GmemDDEShare + GmemMoveable, size + 1); IF h = 0 THEN ShowError.Do("Clipboard.PutToClipboard"); ShowError.CallStack(TRUE) ELSE adr := Win32.GlobalLock(h); IF h = 0 THEN ShowError.Do("Clipboard.PutToClipboard"); ShowError.CallStack(TRUE) ELSE Texts.OpenReader(R, T, beg); size := 0; WHILE Texts.Pos(R) < end DO Texts.Read(R, ch); S.PUT(adr, Win32.OberonToWin[ORD(ch)]); INC(adr); IF ch = 0DX THEN S.PUT(adr, 0AX); INC(adr) END END ; S.PUT(adr, 0X); Win32.GlobalUnlock(h); data := Win32.SetClipboardData(CFText, h) END END ; Win32.CloseClipboard; END ; NEW(oberonClipboard); Texts.OpenBuf(oberonClipboard); Texts.Save(T, beg, end, oberonClipboard) END PutToClipboard; PROCEDURE GetFromClipboard (VAR T: Texts.Text); VAR done: BOOLEAN; h, adr, adr0: LONGINT; ch, ch2: CHAR; R: Texts.Reader; buf2: Texts.Buffer; different: BOOLEAN; BEGIN done := Win32.OpenClipboard(Win32.Display); T := NIL; IF done THEN h := Win32.GetClipboardData(CFText); IF h # NULL THEN adr := Win32.GlobalLock(h); adr0 := adr; IF adr # NULL THEN T := TextFrames.Text(""); IF oberonClipboard # NIL THEN NEW(buf2); Texts.OpenBuf(buf2); Texts.Copy(oberonClipboard, buf2); Texts.Insert(T, 0, buf2); Texts.OpenReader(R, T, 0); Texts.Read(R, ch2); different := FALSE ELSE different := TRUE END ; S.GET(adr, ch); INC(adr); WHILE (ch # 0X) & ~different DO IF ch = 0AX THEN S.GET(adr, ch); INC(adr) END ; IF ch # 0X THEN IF Win32.WinToOberon[ORD(ch)] # ch2 THEN different := TRUE ELSE Texts.Read(R, ch2); S.GET(adr, ch); INC(adr) END END END ; IF different THEN (* text in Windows clipboard is different from that in Oberon clipboard, use text from Windows clipboard, i.e. delete previously inserted text and copy characterwise as would have been copied in the previous Clipboard version *) Texts.Delete(T, 0, T.len); adr := adr0; S.GET(adr, ch); INC(adr); WHILE ch # 0X DO Texts.Write(W, Win32.WinToOberon[ORD(ch)]); IF ch = 0DX THEN INC(adr) (* skip line feed *) END ; S.GET(adr, ch); INC(adr); END ; Texts.Append(T, W.buf); END ; Win32.GlobalUnlock(h) END END ; Win32.CloseClipboard ELSE IF oberonClipboard # NIL THEN NEW(buf2); Texts.OpenBuf(buf2); Texts.Copy(oberonClipboard, buf2); Texts.Insert(T, 0, buf2) END END END GetFromClipboard; PROCEDURE Cut*; VAR T: Texts.Text; beg, end, time: LONGINT; BEGIN Oberon.GetSelection(T, beg, end, time); IF time > 0 THEN PutToClipboard(T, beg, end); Texts.Delete(T, beg, end) END END Cut; PROCEDURE Copy*; VAR T: Texts.Text; beg, end, time: LONGINT; BEGIN Oberon.GetSelection(T, beg, end, time); IF time > 0 THEN PutToClipboard(T, beg, end) END END Copy; PROCEDURE Paste*; VAR T: Texts.Text; M: Oberon.CopyOverMsg; BEGIN GetFromClipboard(T); IF T # NIL THEN M.text := T; M.beg := 0; M.end := T.len; Viewers.Broadcast(M); END END Paste; PROCEDURE Capture* (x, y, w, h: LONGINT); (* w, h > 0 *) CONST SRCCOPY = 0CC0020H; VAR done: BOOLEAN; hnd, bitmap, oldbitmap, hdc: LONGINT; BEGIN done := Win32.OpenClipboard(Win32.Display); IF done THEN hdc := Win32.CreateCompatibleDC(Win32.hdcDisp); bitmap := Win32.CreateCompatibleBitmap(Win32.hdcDisp, w, h); oldbitmap := Win32.SelectObject(hdc, bitmap); Win32.BitBlt(hdc, 0, 0, w, h, Win32.hdcDisp, x, Display.Height-(y+h), SRCCOPY); Win32.EmptyClipboard; hnd := Win32.SetClipboardData(CFBitmap, bitmap); Win32.CloseClipboard; oldbitmap := Win32.SelectObject(hdc, oldbitmap); Win32.DeleteDC(hdc); END END Capture; PROCEDURE Order (VAR a, b: INTEGER); VAR swap: INTEGER; BEGIN IF a > b THEN swap := a; a := b; b := swap END END Order; PROCEDURE DrawFrame (x1, y1, x2, y2: INTEGER); BEGIN Order (x1, x2); Order (y1, y2); Display.ReplConst (Display.white, x1, y1, x2 - x1, 1, Display.invert); Display.ReplConst (Display.white, x1, y1, 1, y2 - y1, Display.invert); Display.ReplConst (Display.white, x1, y2, x2 - x1, 1, Display.invert); Display.ReplConst (Display.white, x2, y1, 1, y2 - y1, Display.invert) END DrawFrame; PROCEDURE Snapshot*; (* takes a snapshot of the marked viewer, or the whole display if no viewer is marked *) VAR cw, ch, x, y, w, h: LONGINT; V: Viewers.Viewer; drag: ARRAY 10 OF CHAR; keys: SET; x1, x2, y1, y2, xold, yold: INTEGER; BEGIN In.Open; In.Name(drag); IF In.Done & (drag = "drag") THEN REPEAT Input.Mouse (keys, x1, y1) UNTIL (keys # {}) OR (Input.Available () # 0); xold := x1; yold := y1; WHILE (keys = {2}) & (Input.Available () = 0) DO Input.Mouse (keys, x2, y2); IF (x2 # xold) OR (y2 # yold) THEN DrawFrame (x1, y1, xold, yold); DrawFrame (x1, y1, x2, y2); xold := x2; yold := y2 END END ; DrawFrame (x1, y1, xold, yold); Order (x1, x2); Order (y1, y2); Capture(x1, y1, x2-x1, y2-y1) ELSIF Oberon.Pointer.on THEN V := Oberon.MarkedViewer(); IF V # NIL THEN x := V.X; y := V.Y; w := V.W; h := V.H; Win32.GetClientSize(cw, ch); IF x + w > cw THEN DEC(w, x+w-cw) END ; IF y < Display.Height - ch THEN INC(y, Display.Height - ch); DEC(h, Display.Height - ch) END ; IF (w > 0) & (h > 0) THEN Oberon.RemoveMarks(SHORT(x), SHORT(y), SHORT(w), SHORT(h)); Capture(x, y, w, h) END END ELSE Win32.GetClientSize(w, h); y := Display.Height - h; Capture(0, y, w, h); END ; END Snapshot; BEGIN Texts.OpenWriter(W) END Clipboard. System.Free Clipboard ~ Clipboard.Cut Clipboard.Copy Clipboard.Paste Clipboard.Snapshot Clipboard.Snapshot drag