#define INCL_DOSDEVIOCTL
#define INCL_DOSFILEMGR
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
  USHORT ParmLength;
  USHORT PowerFlags;
  UCHAR  ACStatus;
  UCHAR  BatteryStatus;
  UCHAR  BatteryLife;
} PARMPACK;

INT main(VOID)
{
  HFILE    DevHandle;
  ULONG    ulCategory;
  ULONG    ulFunction;
  PARMPACK ParmPack;
  ULONG    ulParmLen;
  UCHAR    uchDataArea;
  ULONG    ulDataLen;
  APIRET   rc;
  ULONG    ulAction;


  rc = DosOpen("APM$", &DevHandle, &ulAction, 0, FILE_NORMAL, FILE_OPEN, OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, 0);
  switch(rc)
  {
    case   0: break;
    case 110: printf("You must have the APM device driver installed.\n");
              return 1;
              break;
    default : printf("DosOpen error: rc = %u\n", rc);
              return rc;
  }

  ulCategory  = IOCTL_POWER;
  ulFunction  = POWER_GETPOWERSTATUS;
  ulParmLen   = sizeof(ParmPack);
  ulDataLen   = sizeof(uchDataArea);
  ParmPack.ParmLength = 7;

  /****************************************************************************
   * I use the ANSI escape sequences because thunking the 16 bit calls is too *
   * much work!                                                               *
   ****************************************************************************/
  printf("[2J");  //clear screen
  printf("[s");   //save cursor position

  while (TRUE)     //do forever
  {
    rc = DosDevIOCtl(DevHandle, ulCategory, ulFunction, &ParmPack, sizeof(ParmPack), &ulParmLen, &uchDataArea, sizeof(uchDataArea), &ulDataLen);
    if (rc != 0)
    {
      printf("DosDevIOCtl error: return code = %u\n", rc);
      printf("                   Date area   = %c\n", uchDataArea);
      return rc;
    }

    if (!ParmPack.PowerFlags)
    {
      printf("Power Management support is currently disabled.\n");
      return 1;
    }

    printf("[u");     //restore cursor position

    printf("Plugged in    : ");
    switch(ParmPack.ACStatus)
    {
      case   0: printf("No     ");  break;
      case   1: printf("Yes    ");  break;
      case 255: printf("Unknown");  break;
    }
    printf("\n");

    printf("Battery Status: ");
    switch(ParmPack.BatteryStatus)
    {
      case   0: printf("High    "); break;
      case   1: printf("Low     "); break;
      case   2: printf("Critical"); break;
      case   3: printf("Charging"); break;
      case 255: printf("Unknown "); break;
    }
    printf("\n");

    printf("Battery Life  : %d%%  \n", ParmPack.BatteryLife);
    DosSleep(500);
  }

  DosClose(DevHandle);
}
