MODULE ComEnumRect;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	references	= "adapted from EnumRect sample in "Inside OLE", 2nd ed."
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)


	IMPORT COM, WinApi;
	
	
	CONST rects = 15;
	
	
	TYPE
		IEnumRECT* = POINTER TO
								ABSTRACT RECORD ["{00021140-0000-0000-C000-000000000046}"] (COM.IUnknown) END;
		
		
		EnumRECT = POINTER TO RECORD (IEnumRECT)
			cur: INTEGER;
			data: ARRAY rects OF WinApi.RECT;
		END;
		
		
	(* ---------- abstract interface methods ---------- *)
	
	(* QueryInterface, AddRef, Release inherited from COM.IUnknown *)
		
	PROCEDURE (this: IEnumRECT) Next* (num: INTEGER; OUT elem: ARRAY [untagged] OF WinApi.RECT;
														OUT [nil] fetched: INTEGER): COM.RESULT, NEW, ABSTRACT;
	PROCEDURE (this: IEnumRECT) Skip* (num: INTEGER): COM.RESULT, NEW, ABSTRACT;
	PROCEDURE (this: IEnumRECT) Reset* (): COM.RESULT, NEW, ABSTRACT;
	PROCEDURE (this: IEnumRECT) Clone* (OUT enum: IEnumRECT): COM.RESULT, NEW, ABSTRACT;
	
		
	(* ---------- interface implementation ---------- *)
	
	(* use default QueryInterface implementation *)
	
	(* AddRef & Release implemented implicitly by the compiler *)
	
	PROCEDURE (this: EnumRECT) Next (num: INTEGER; OUT elem: ARRAY [untagged] OF WinApi.RECT;
														OUT [nil] fetched: INTEGER): COM.RESULT;
		VAR n: INTEGER;
	BEGIN
		n := 0;
		IF VALID(fetched) THEN fetched := 0
		ELSIF num # 1 THEN RETURN WinApi.S_FALSE
		END;
		IF this.cur < rects THEN
			WHILE (this.cur < rects) & (num > 0) DO
				elem[n] := this.data[this.cur];
				INC(this.cur); INC(n); DEC(num)
			END;
			IF VALID(fetched) THEN fetched := n END;
			RETURN WinApi.S_OK
		END;
		RETURN WinApi.S_FALSE
	END Next;
	
	PROCEDURE (this: EnumRECT) Skip (num: INTEGER): COM.RESULT;
	BEGIN
		IF this.cur + num < rects THEN
			INC(this.cur, num); RETURN WinApi.S_OK
		ELSE RETURN WinApi.S_FALSE
		END
	END Skip;
	
	PROCEDURE (this: EnumRECT) Reset (): COM.RESULT;
	BEGIN
		this.cur := 0; RETURN WinApi.S_OK
	END Reset;
	
	PROCEDURE (this: EnumRECT) Clone (OUT enum: IEnumRECT): COM.RESULT;
		VAR new: EnumRECT;
	BEGIN
		NEW(new);
		IF new # NIL THEN
			new.cur := this.cur;
			new.data := this.data;
			enum := new;
			RETURN WinApi.S_OK
		ELSE RETURN WinApi.E_OUTOFMEMORY
		END
	END Clone;
	
	
	PROCEDURE CreateRectEnumerator* (OUT enum: IEnumRECT);
		VAR new: EnumRECT; i: INTEGER;
	BEGIN
		NEW(new);
		IF new # NIL THEN
			new.cur := 0; i := 0;
			WHILE i < rects DO
				new.data[i].left := i;
				new.data[i].top := i * 2;
				new.data[i].right := i * 3;
				new.data[i].bottom := i * 4;
				INC(i)
			END;
			enum := new
		END
	END CreateRectEnumerator;
		

END ComEnumRect.
