Welcome, Guest. Please login or register.

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

Description:

0 Members and 1 Guest are viewing this topic.

Offline nyteschaydeTopic starter

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 643
    • Show only replies by nyteschayde
    • http://www.nyteshade.com
[C] CLI Window Pointer
« on: February 11, 2018, 10:43:11 PM »
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.

*UPDATE*

I'm an idiot. I was trying to open dos.library with a DOSBase variable, guessing the name, when in fact, it was DosLibrary instead. Sigh. C'est la vie.
« Last Edit: February 12, 2018, 05:39:52 AM by nyteschayde »
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Offline olsen

Re: [C] CLI Window Pointer
« Reply #1 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.
 

guest11527

  • Guest
Re: [C] CLI Window Pointer
« Reply #2 on: February 12, 2018, 08:23:35 AM »
As Olaf already pointed out, pr->WindowPtr is not related to that. It is rather a pointer to a Screen (sic!) where Dos will put error requesters in case something is to report to the user.

First: Why do you need the window pointer? In most cases, you should avoid getting it because a) the CLI does not need to have window in first place, because it might either run in the background or run over AUX: and b) because it will de-iconify the shell window. Dimensions of the shell window, even if iconified, are better obtained by CSI-sequences.

Two packets are responsible for this: ACTION_DISK_INFO (sic!) will get the window pointer from a console-type output stream. I need to dig out where in the InfoData exactly, but it mis-uses this structure which otherwise contains the disk fill state.

Then, as soon as you are done with the pointer, also (!) use ACTION_UNDISK_INFO to release the pointer. Failing to do that will cause the CLI window failing to iconify again, which might be very disturbing to the user. Reason is, of course, that for that the console needs to close the window, but it cannot if some other program might be still using the pointer.
 

Offline olsen

Re: [C] CLI Window Pointer
« Reply #3 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 nyteschaydeTopic starter

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 643
    • Show only replies by nyteschayde
    • http://www.nyteshade.com
Re: [C] CLI Window Pointer
« Reply #4 on: February 12, 2018, 04:15:49 PM »
I would love to see the right way to do this with 1.2/1.3 if possible. 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.

Almost everything in dosextens is this way. If you show a better way for 2.0+ as an alternative, that would be amazing. Thanks.  

Thomas and Olaf, thank you both. You two are some of the most knowledgeable and forthcoming folks here. Much appreciated.

Thomas, I am attempting to move and resize the window in question and possibly add some menus to it. Making some utilities to make my startup scripts more powerful under 1.2/1.3. I%&$#?@!%&$#?@!%&$#?@!8217;ll throw them on aminet when I%&$#?@!%&$#?@!%&$#?@!8217;m done.
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Offline nyteschaydeTopic starter

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 643
    • Show only replies by nyteschayde
    • http://www.nyteshade.com
Re: [C] CLI Window Pointer
« Reply #5 on: February 12, 2018, 04:21:25 PM »
What about the opposite? Can you programmatically attach a shell to a window you choose to open? Where on Earth did you find out how to do this?! Lol. I have been scouring the web and my books.

Finally, in your example, do I need to invoke/message ACTION_UNDISK_INFO as mentioned by Thomas?
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Offline olsen

Re: [C] CLI Window Pointer
« Reply #6 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 #7 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 ;)
 

guest11527

  • Guest
Re: [C] CLI Window Pointer
« Reply #8 on: February 12, 2018, 09:34:33 PM »
Quote from: nyteschayde;836058
Almost everything in dosextens is this way. If you show a better way for 2.0+ as an alternative, that would be amazing. Thanks.  

Here you go:
Code: [Select]
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/console.h>
#include <devices/keymap.h>
#include <devices/conunit.h>
#include <libraries/diskfont.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <intuition/intuition.h>

#define ACTION_UNDISK_INFO  513L
{
struct InfoData __aligned  infoData;
struct Window *window;
struct MsgPort *con;
...
                    con = (struct MsgPort *)THISPROC->pr_ConsoleTask)
                    DoPkt1(con,ACTION_DISK_INFO,MKBADDR(&infoData));
                    if (window = (struct Window *)infoData.id_VolumeNode)
                    {
                        /* do something with the window */
                    }
                    DoPkt1(con,ACTION_UNDISK_INFO,MKBADDR(&infoData));
}

Quote from: nyteschayde;836058
Thomas, I am attempting to move and resize the window in question and possibly add some menus to it.
Move and resize will work. But menus: How do you attempt to get the information that the user picked a menu? This you only get via RAW console events, and for that the console must be in RAW mode (at least for the traditional CON: handler - ViNCed can do that).
Ok, you *could* add a IDCMP port to the window, and it would (still) work due to the special nature of the console device and its input handler, but in general: You should expect that there is already a menu, and it is not necessarily yours.
 

Offline nyteschaydeTopic starter

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 643
    • Show only replies by nyteschayde
    • http://www.nyteshade.com
Re: [C] CLI Window Pointer
« Reply #9 on: February 12, 2018, 09:43:18 PM »
@Thomas, I was planning on adding IDCMP code to the window. I figured that I could make some likely assumptions and document the caveats, maybe do some version checking.

Speaking of which, what is the best way to programmatically check the version of files. I also forgot how to specify the version of a file that is detectable from programs like 'Version'. Version under 1.2/1.3 doesn't seem to be check the version of files other than loaded libraries; or I am doing something wrong.

Again, thanks for your help. Can either of you confirm that ReadArgs was introduced in V36+?
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

guest11527

  • Guest
Re: [C] CLI Window Pointer
« Reply #10 on: February 12, 2018, 09:45:37 PM »
Quote from: nyteschayde;836059
What about the opposite? Can you programmatically attach a shell to a window you choose to open?
Well. Yes. One can. There is a highly undocumented and not fully reliable possibility on Kick 1.2, but I would *really really* not recommend it. If I recall correctly, it was something along the lines of hacking the Window pointer into the dol_Startup field of the handler, opening CON:, undo the stunt, and "hope all the best" that nobody else will attempt to open something at the same time. I afraid this trick will even work with 3.1, though it really should not.

One way or another: Don't.


VINCed can, by using a proper string in the "Path" by which you "open the window". There is more in the manual, but it was something weird such as

"VNC:////W"

and it will place itself into that window.

However: If you want to go that far, and play with menus, and window resizes: Instead of going through the thorny road of undocumented BCPL nonsense, there is a quite beautify exec device which will happily open on every window where you decided to place it, and that is the "console.device". There is really not that much difference between a window equipped with a "RAW:" handler, and a window in which the console.device runs. Actually, for the native Amiga "CON" handler, this is almost exactly the same, except that RAW: adds a rather thin layer around the "console.device" to make the whole thing work like a DOS (Tripos) handler instead of an exec device.

Then, however, with the console.device, you need to handle editing yourself. And you do not get a shell in there. The shell requires a "tripos handler".

Quote from: nyteschayde;836059
Where on Earth did you find out how to do this?! Lol. I have been scouring the web and my books.
Oh. "Use the source, Luke".


Quote from: nyteschayde;836059
Finally, in your example, do I need to invoke/message ACTION_UNDISK_INFO as mentioned by Thomas?
Please. Do. As said by Olaf, the original CON does not have an iconification button, so there it does not matter - but other shells do. But, all that feature will go away once you have borrowed the window pointer and haven't given it back. Anoyance to the user. Be kind, return what you have borrowed when you are done.
 

guest11527

  • Guest
Re: [C] CLI Window Pointer
« Reply #11 on: February 12, 2018, 09:50:32 PM »
Quote from: nyteschayde;836068
Speaking of which, what is the best way to programmatically check the version of files.
In source? Scan for "$VER:" and interpret the string that follows. But that is a "relatively new" invention. In Amiga history. It was somewhere around 2.0 where this was added.

Quote from: nyteschayde;836068
Again, thanks for your help. Can either of you confirm that ReadArgs was introduced in V36+?
Well. Ehem. Is this a trick question? Actually, the obvious answer is "yes", as it appears in dos.library in V36. However, it was always part of tripos, as "rdargs()", though not accessible by C programmer, not part of the dos.library, and only reachable through a lot of stunts via the mystical "GlobVec" of BCPL. So, in a sense "no, I cannot confirm that". But for all practical matters, you are right.
 

Offline nyteschaydeTopic starter

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 643
    • Show only replies by nyteschayde
    • http://www.nyteshade.com
Re: [C] CLI Window Pointer
« Reply #12 on: February 12, 2018, 10:44:23 PM »
Quote from: Thomas Richter;836070

Well. Ehem. Is this a trick question? Actually, the obvious answer is "yes", as it appears in dos.library in V36. However, it was always part of tripos, as "rdargs()", though not accessible by C programmer, not part of the dos.library, and only reachable through a lot of stunts via the mystical "GlobVec" of BCPL. So, in a sense "no, I cannot confirm that". But for all practical matters, you are right.


Care to document how and demystify it? Others look at these forums too. ;) If there is a way to use the call in 2.x+ compatible code that is being written to be 1.x compatible in many ways, it could be useful.
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Offline nyteschaydeTopic starter

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 643
    • Show only replies by nyteschayde
    • http://www.nyteshade.com
Re: [C] CLI Window Pointer
« Reply #13 on: February 12, 2018, 10:46:53 PM »
Quote from: Thomas Richter;836069

Please. Do. As said by Olaf, the original CON does not have an iconification button, so there it does not matter - but other shells do. But, all that feature will go away once you have borrowed the window pointer and haven't given it back. Anoyance to the user. Be kind, return what you have borrowed when you are done.


There is no define ACTION_UNDISK_INFO anywhere in the Amiga Developer's CD. How do I send that message.
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

guest11527

  • Guest
Re: [C] CLI Window Pointer
« Reply #14 on: February 13, 2018, 06:36:03 AM »
Quote from: nyteschayde;836072
There is no define ACTION_UNDISK_INFO anywhere in the Amiga Developer's CD. How do I send that message.
By using the code I provided?
Code: [Select]
#define ACTION_UNDISK_INFO 513L