Welcome, Guest. Please login or register.

Author Topic: [C] CLI Window Pointer  (Read 5656 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline olsen

Re: [C] CLI Window Pointer
« on: February 12, 2018, 07:33:10 AM »
Quote from: nyteschayde;836047
I have been failing to get a handle on the window the CLI is running from in C. The call to FindTask(0L) will land me both a structure to Task as well as Process, the overlapping technique a popular one, I%&$#?@!%&$#?@!%&$#?@!8217;m finding. However attempts to use the data in this structure do not work.

Process has .pr_WindowPtr which is typed as APTR. I thought it would be easy but thus far it hasn%&$#?@!%&$#?@!%&$#?@!8217;t worked.


The Process->pr_WindowPtr field has a different purpose. It can be used to shut down the requesters which dos.library will show (e.g. "Please insert volume xxx"), for example (setting pr_WindowPtr = (APTR)-1 will do that; dos.library functions will then work as if the user had always clicked on the "Cancel" button of the requester that isn't opened), or it can be used to make these requesters open on the same screen as a particular window. If you leave it set to NULL, then those requesters will always open on the default public screen (which is usually the Workbench screen).

Getting a handle on the window associated with a shell is a completely different operation, because it involves talking to the console window handler which opened that window and made it accessible to the shell.

I think I could knock some example code together which would ask the console handler to return the window pointer for you if you need it. Of course, it's harder to do this with Kickstart 1.2/1.3 than with 2.0 and beyond.
 

Offline olsen

Re: [C] CLI Window Pointer
« Reply #1 on: February 12, 2018, 04:08:46 PM »
Quote from: nyteschayde;836047
I have been failing to get a handle on the window the CLI is running from in C. The call to FindTask(0L) will land me both a structure to Task as well as Process, the overlapping technique a popular one, I%&$#?@!%&$#?@!%&$#?@!8217;m finding. However attempts to use the data in this structure do not work.

Process has .pr_WindowPtr which is typed as APTR. I thought it would be easy but thus far it hasn%&$#?@!%&$#?@!%&$#?@!8217;t worked.

Here's something that should get you somewhere :)

Code: [Select]
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <devices/conunit.h>

#include <stdio.h>

#ifndef MKBADDR
#define MKBADDR(p) (((ULONG)(p)) >> 2)
#endif /* MKBADDR */

LONG
send_packet(port,action,num_args,args)
struct MsgPort *port;
LONG action;
int num_args;
LONG * args;
{
   struct Process * this_process = (struct Process *)FindTask(NULL);
   struct MsgPort * reply_port = &this_process->pr_MsgPort;
   struct StandardPacket * packet;
   LONG result;

   packet = (struct StandardPacket *)AllocMem(sizeof(*packet),
      MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
   if(packet != NULL)
   {
      LONG * packet_args = &packet->sp_Pkt.dp_Arg1;
      int i;

      packet->sp_Msg.mn_Node.ln_Name = (char *)&packet->sp_Pkt;
      packet->sp_Pkt.dp_Link         = &packet->sp_Msg;
      packet->sp_Pkt.dp_Port         = reply_port;
      packet->sp_Pkt.dp_Type         = action;

      if(num_args > 7)
         num_args = 7;

      for(i = 0 ; i < num_args ; i++)
         packet_args[i] = args[i];

      PutMsg(port, packet);

      WaitPort(reply_port);
      GetMsg(reply_port);

      result = packet->sp_Pkt.dp_Res1;

      FreeMem(packet,sizeof(*packet));
   }
   else
   {
      result = DOSFALSE;
   }

   return(result);
}

int
main(argc,argv)
int argc;
char **argv;
{
   struct Process * this_process = (struct Process *)FindTask(NULL);
   struct InfoData * id;

   if(this_process->pr_ConsoleTask != NULL)
   {
      id = (struct InfoData *)AllocMem(sizeof(*id),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
      if(id != NULL)
      {
         LONG args[1];

         args[0] = MKBADDR(id);

         if(send_packet(this_process->pr_ConsoleTask,ACTION_DISK_INFO,1,args))
         {
            struct Window * window;
            struct IORequest * ior;
            struct ConUnit * con_unit;

            window = (struct Window *)id->id_VolumeNode;
            ior = (struct IORequest *)id->id_InUse;
            con_unit = (ior != NULL) ? (struct ConUnit *)ior->io_Unit : NULL;

            printf(&quot;window = 0x%08x\n&quot;, window);
            printf(&quot;console unit = 0x%08x\n&quot;, con_unit);
            printf(&quot;disk type = 0x%08x\n&quot;, id->id_DiskType);
         }

         FreeMem(id,sizeof(*id));
      }
   }

   return(0);
}

Knowing which window is attached to the shell might not get you anywhere, though. It is traditionally much easier to open a window all on your own through intuition.library than to try and harness whatever the shell is attached to. For one thing, you have much better control over how your window looks like and what it can do. Also, input processing tends to be way more complicated if you talk to it through a file handle, since you will have to parse the byte stream as if it were an early 1990'ies smart terminal. In that direction things will only get progressively more difficult with each step.

That code example above is also a good example of how difficult talking to the dos.library used to be 1985-1989. With Kickstart 2.0 and beyond the whole exercise becomes much shorter, replacing the entirety of the send_packet() function with a call to DoPkt1().
 

Offline olsen

Re: [C] CLI Window Pointer
« Reply #2 on: February 12, 2018, 05:52:42 PM »
Quote from: nyteschayde;836058
I would love to see the right way to do this with 1.2/1.3 if possible.
You got it :)

Quote
Also if you could list which structures the APTRs in struct Process are actually referencing that would be wonderful. None of the many books I have discuss this.
Hm... there isn't actually much in the Process structure that is useful for application software. Most of this is being used by dos.library itself and the shell (CLI). The pr_WindowPtr is just about the only thing that's useful for 'C' programmers. As for the rest, tinkering with it may have strange side-effects in Kickstart 1.x, may have no effects on Kickstart 2.x and beyond, and all too often requires the kind of insight into the dos.library, the file system and the shell which once gained makes you wish you hadn't cluttered up your brain with such exquisite almost useless but still baffling information.

Here's one such baffling thing which might be mistaken for a nugget under poor lighting conditions: on the Amiga the program execution stack grows "downward" (towards address 0) when new parameters are stored on the stack. This is part of the ABI, if you will. Now there's this pr_StackBase field in the Process structure, which has a peculiar purpose. Within the original dos.library the program execution stack did not grow "downward", it would grow upward instead. This is why there is the pr_StackBase field: as soon as code execution has passed through the looking glass, its stack is turned downside up and when execution leaves the dos.library, it is returned back to normal again. This oddity has consequences for the minimum stack size used by a Process. In Kickstart 1.2 the minimum recommended stack size was given as 4000 bytes (or so). It's not that the operating system uses that much, although application software can, of course, but the problem is that if you are shaving the stack frame size limits very closely, calling a dos.library function can trash the bottom of your execution stack (for the dos.library kernel the floor of the 'C' stack is what it considers the stack's ceiling). This means that the 4000 byte minimum recommended stack space includes a healthy safety margin for dos.library, so that it does not trash the "normal" stack so easily.
 

Offline olsen

Re: [C] CLI Window Pointer
« Reply #3 on: February 12, 2018, 06:23:59 PM »
Quote from: nyteschayde;836059
What about the opposite? Can you programmatically attach a shell to a window you choose to open?
Yes, that's actually possible even unter Kickstart 1.x. However, it requires the use of undocumented operating system functions and knowledge of how the con-handler (responsible for the CON: and RAW: devices) deals with the startup message it receives when it is asked to connect a file handle to a window.

Quote
Where on Earth did you find out how to do this?! Lol. I have been scouring the web and my books.
Much of this information is still available, but it is only found in archives which predate the Internet as we know it by 6-8 years. For example, information on how to tell con-handler to use a ready-made window instead of opening its own can be found in an October 1986 posting on usenet, in the net.micro.amiga group. It's called "Creating a DOS Window in a Custom Screen" and it was written by Commodore engineer Andy Finkel. Try Google Groups, the article is still there.

Much of the early information which is still relevant (sometimes painfully so) can be found in example code posted by Commodore engineers on usenet, which subsequently found its way onto the AmigaLibDisks ("Fish disks"). How to obtain the window attached to a shell is explained in a series of postings on usenet under the subject "MsgPorts, DOS, ACTION_SCREEN_MODE help needed". The code which I cooked up for you is suspicously similar to the contents of that article, I might say ;)

Finally, there is the official technical documentation published by Commodore under the name "Amiga Mail". If you can find it, the CATS Developer CD as well as the Amiga Developer CDs contain the complete archive.

Slightly more difficult to find is the "Amiga Guru book" (and its precursor, the German language "Das Amiga Guru-Buch") written by Ralph Babel, who spent years researching dos.library and the fundamentals upon which it rests. The results were self-published in 1993/1989, respectively. If there is anything worth knowing and understanding about this subject you will find that Ralph Babel can thoroughly explain it. Do you enjoy reading Donald Knuth detailing the breadth, the width and the depth of even the most humble algorithms? Then the "Amiga guru book" might just be the book for you.

Guys like Thomas and me have been around for a while, and we couldn't help picking up a lot of Amiga technical history along the way. Not that it amounts to much in this day and age when the Amiga is at best considered a significant historical stepping stone for the evolution of personal computers, but at times it feels like we might be carrying knowledge around which is important and useful ;)

Quote
Finally, in your example, do I need to invoke/message ACTION_UNDISK_INFO as mentioned by Thomas?
To the best of my knowledge no such packet did exist in the Kickstart 1.x days, and Kickstart 2.x and beyond are neither harmed nor insulted when asked to volunteer information about the window, the console unit and the mode of operation of the console file handle attached to a shell window ;)