(c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice, and 
is provided "as is" without warranty of any kind, either expressed or implied.  
The entire risk as to the use of this information is assumed by the user.



                  Tricks with AmigaDOS, Part II
 
                       by Andy Finkel


As you may recall, part one was all about finding the window pointer and
console.device IO Request Block from a DOS window.  Part II is about how
to go the other way: make an Intuition window into a DOS window.  

Specifically, this is used to get a DOS window to open in a custom screen. 
There are reasons why this is something you might want to do, such as using 
the Execute command to initialize a new disk in a program that doesn't use 
the Workbench screen.  Or for those of you writing shells, under V1.2 the 
ability to switch a window in or out of RAW mode via an AmigaDOS packet 
can be used to good advantage.

There are 3 files:  window.c which contains most of the program, console.asm
which contains the assembler interface calls to the BCPL routines of 
AmigaDOS, and window.i, the include file I use when I am doing tricks
like this.

Two warnings:

1) I only compiled this under Greenhills C.  Some slight changes may be 
   needed for other compilers.  Also, I'm only linking with the amiga.lib on 
   this one.

2) I used 3 of the BCPL global routines.  They are loaddevice, finddevice
   and send-packet.







***********************************************************************
* window.i
* contents: useful macros/definitions from Tim King
* 9/15/86
*
* (c) 1986 Commodore-Amiga, Inc.
* This file may be used in any manner, as long as this copyright notice
* remains intact.
* 		andy finkel
*		Commodore-Amiga
*
***********************************************************************

procst  macro
        link    a6,\1
        movem.l \2,-(sp)
        sub.l   z,z
        endm

return  macro
        movem.l (sp)+,\1
        unlk    a6
        rts
        endm

callg   macro
        move.l  a6,-(sp)
        move.l  #\1,d0
        move.l  _DOSBase,a6
        jsr     -28(a6)
        move.l  (sp)+,a6
        endm
 
* Registers
Z       equr    a0
*P      equr    a1
*G      equr    a2
L       equr    a3
B       equr    a4
S       equr    a5
R       equr    a6

arg1    equ     8
arg2    equ     12
arg3    equ     16
arg4    equ     20

*****************************
* end of file window.i
*****************************

-------------------------CUT HERE -------------------------------
/*        window.c
   or, how to open a DOS window in a custom screen
   and do something like format a disk
   (c) 1986 Commodore-Amiga, Inc.
   This file may be used in any manner, as long as this copyright notice
   remains intact.
  		andy finkel
 		Commodore-Amiga
*/
#include "exec/types.h"
#include "exec/libraries.h"
#include "graphics/gfx.h"
#include "intuition/intuition.h"
#include "libraries/dos.h"
#include "libraries/dosextens.h"

#define BLUE 0 
#define WHITE 1 
#define BLACK 2 
#define RED 3 

struct GfxBase *GfxBase; 
LONG *IntuitionBase;
LONG *DosBase;

extern struct Library *OpenLibrary();
extern struct Screen *OpenScreen();
extern struct Window *OpenWindow();

extern struct MsgPort  *NewConsole();

struct Window   *window=NULL;
struct Screen   *screen=NULL;
struct MsgPort  *task=NULL;
struct Process  *process=NULL;

LONG handle=NULL;

struct NewScreen ns = {
        0,0,
        320,200,4, /* & depth */
        BLUE,WHITE,
        NULL,  /* viewmodes */
        CUSTOMSCREEN,
        NULL, /* default font */
        "Window Test Program",
        NULL, /* no user gadgets */
        NULL
};

struct NewWindow nw = {
        0, 12,          /* starting position (left,top) */
        320,186,        /* width, height */
        BLUE,WHITE,    /* detailpen, blockpen */
        NULL,  /* flags for idcmp */
        SMART_REFRESH|WINDOWDEPTH|WINDOWSIZING|WINDOWDRAG|ACTIVATE, /* window gadget flags */
        NULL,           /* pointer to 1st user gadget */
        NULL,           /* pointer to user check */
        NULL,            /* no title */
        NULL,           /* pointer to window screen (add after it is open */
        NULL,           /* pointer to super bitmap */
        50,50,         /* min width, height */
        320,200,        /* max width, height */
        CUSTOMSCREEN};

main()
{
if((IntuitionBase = OpenLibrary("intuition.library",0)) == NULL)cleanup(20);
if((DosBase = OpenLibrary(DOSNAME, 0)) == NULL) cleanup(20);
if((GfxBase = OpenLibrary("graphics.library", 0)) ==NULL) cleanup(20);

if((screen=OpenScreen(&ns)) == NULL)cleanup(20);
nw.Screen=screen;
if((window=OpenWindow(&nw)) == NULL)cleanup(20); 

/* Start up new console handler task; pass it new window */

if(!(task = NewConsole(window)))cleanup(20);

/* Change AmigaDOS consoletask location. All later calls to */
/* Open("*") by this process will refer to the new window */

process = (struct Process *)FindTask(NULL); 
process -> pr_ConsoleTask = task;

process->pr_WindowPtr=window; /*reset error screen so requesters appear here*/

if (!(handle = Open("*", MODE_OLDFILE))) { /* get a handle on the window */
    CloseConsole(task); /* open failed, kill our console task */
    cleanup(20);
   }

    Write(handle,"\033[20hHello world\n",17);

    Write(handle,"I'm about to format drive 1\n",28);
/* SAMPLE COMMAND; THIS IS OPTIONAL, FOR DEMO PURPOSES ONLY) */
	Execute("format <* >* drive df1: name test",0,0);

	cleanup(0);
}


cleanup(code)
{
struct Process *process;

process = (struct Process *)FindTask(NULL); /* reset error window */
process->pr_WindowPtr=NULL;
process -> pr_ConsoleTask = NULL;;

if(handle)Close(handle);
if(screen)CloseScreen(screen);

if(GfxBase)CloseLibrary(GfxBase);
if(DosBase)CloseLibrary(DosBase);

OpenWorkBench(); /* just in case */
if(IntuitionBase)CloseLibrary(IntuitionBase); 

exit(code);

}
/* end of file window.c */

-------------------------CUT HERE ---------------------
**********************************************
* console.asm
* 
* contents: code to spawn a new console task  
* From Tim King (more or less)
* (C) 1986 Commodore-Amiga
*
* (c) 1986 Commodore-Amiga, Inc.
* This file may be used in any manner, as long as this copyright notice
* remains intact.
* 		andy finkel
*		Commodore-Amiga
*
************************************
	include	"window.i"

	xdef	_NewConsole
	xdef	_CloseConsole
	xref	_DOSBase

startup	equ	28	offset into device style DevList structure
			* (the include file said the DevList structure
			* needed some work !)

act_end		equ	1007

g_sendpkt	equ	48
g_loaddevice	equ	112
g_finddevice	equ	124

* task = NewConsole(Window)
* create a console task in an already opened window
* and return its handle
 
_NewConsole:
	procst	#0,d2/a2/a5
	move.l	#conname,d1	d1 = address of "CON" string
	lsr.l	#2,d1		arg1 = BCPL address of string
	callg	g_finddevice	get console device node
	move.l	d0,d1		send it in arg1
	lsl.l	#2,d0		d0 = address of node
	move.l	d0,a2		save it in a2
	move.l	#-1,startup(a2)	tell it not to create another window
	move.l	arg1(a6),d2	arg2 = window structure pointer
	callg	g_loaddevice
	clr.l	startup(a2)	zero startup- we're cool now
	return	d2/a2/a5

* CloseConsole( task )
* shutdown the console task
_CloseConsole:
	procst	#0,d2-d4
	move.l	arg1(a6),d2	d2 = destination task
	move.l	#act_end,d3	d3 = action
	callg	g_sendpkt	send the pkt off
	return	d2-d4

	cnop	0,4

conname	dc.b	3,'C','O','N'

	end

****************************
* end of file console.asm
****************************
-------------------------CUT HERE *********************

