//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  Copyright (C) 1999 Alexander S. Aganichev
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  Multitasking.
//  ------------------------------------------------------------------

#include <cstdlib>
#include <gmemall.h>
#include <gutlmtsk.h>

#ifdef __OS2__
#define INCL_BASE
#include <os2.h>
#endif

#ifdef __WIN32__
#include <windows.h>
#endif

#ifdef __GNUC__
#include <unistd.h>
#endif

#ifdef __BEOS__
#include <OS.h> // sz: snooze() declaration ...
#endif

//  ------------------------------------------------------------------
//  Global multitasker data

GMTsk gmtsk;


//  ------------------------------------------------------------------

GMTsk::GMTsk() {

  detected = GMTSK_NONE;
  name = "";
  #if defined(__DJGPP__)
  detected = GMTSK_DOS;
  name = "DPMI32";
  #elif defined(__UNIX__)
  detected = GMTSK_LINUX;
  name = "UNIX";
  #else
  if(desqview())
    return;
  if(win32())
    return;
  if(os2())
    return;
  if(windows())
    return;
  dosint28();
  #endif
}


//  ------------------------------------------------------------------

int GMTsk::os2() {

  #if defined(__OS2__)
  detected = GMTSK_OS2;
  name = "OS/2";
  #elif !defined(__GNUC__) && !defined(_MSC_VER)
  if(_osmajor >= 10) {
    detected = GMTSK_OS2;
    name = "OS/2";
  }
  #endif
  return detected;
}


//  ------------------------------------------------------------------

int GMTsk::win32() {

  #if defined(__WIN32__)
  #if defined(__BORLANDC__)
  if(GetProcAddress(GetModuleHandle("kernel32.dll"), "Borland32")) {
    name = "DOS (32RTM.EXE)";
    detected = GMTSK_DOS;
    return detected;
  }
  #endif
  detected = GMTSK_W32;
  name = "Win32";
  #endif
  return detected;
}


//  ------------------------------------------------------------------

int GMTsk::windows() {

  #if defined(__MSDOS__) && !defined(__DJGPP__)
  i86 cpu;
  cpu.ax(0x352F);
  cpu.genint(0x21);
  if(cpu.es() != 0) {
    cpu.ax(0x1600);
    cpu.genint(0x2F);
    if(cpu.ax() & 0x007F) {
      detected = GMTSK_WINDOWS;
      name = "Windows";
    }
  }
  #endif
  return detected;
}


//  ------------------------------------------------------------------

int GMTsk::desqview() {

  #if defined(__MSDOS__) && !defined(__DJGPP__)
  i86 cpu;
  cpu.cx(0x4445);
  cpu.dx(0x5351);
  cpu.ax(0x2B01);
  cpu.genint(0x21);
  if(cpu.al() != 0xFF) {
    if(cpu.bx()) {
      detected = GMTSK_DESQVIEW;
      name = "DESQview";
    }
  }
  #endif
  return detected;
}


//  ------------------------------------------------------------------

int GMTsk::dosint28() {

  #if defined(__MSDOS__) && !defined(__DJGPP__)
  detected = GMTSK_DOS;
  name = "DOS";
  #endif

  return detected;
}


//  ------------------------------------------------------------------

void GMTsk::timeslice() {

  #if defined(__DJGPP__)
  __dpmi_yield();
  #else
  #if defined(__MSDOS__)
  i86 cpu;
  #endif

  switch(detected) {
    #if defined(__UNIX__)
    case GMTSK_LINUX:
      #if defined(__BEOS__)
        snooze(5000);
      #else
        usleep(5000);
      #endif
      break;
    #endif
    #if defined(__WIN32__)
    case GMTSK_W32:
      Sleep(5);
      break;
    case GMTSK_DOS:
      Sleep(5);
      break;
    #endif
    #if defined(__MSDOS__) || defined(__OS2__)
    case GMTSK_OS2:
      #if defined(__OS2__)
      DosSleep(5);
      break;
      #endif
      // Drop through if this is a DOS version
    #if defined(__MSDOS__)
    case GMTSK_WINDOWS:
      cpu.ax(0x1680);
      cpu.genint(0x2F);
      break;
    case GMTSK_DESQVIEW:
      cpu.ax(0x1000);
      cpu.genint(0x15);
      break;
    case GMTSK_DOS:
      cpu.genint(0x28);
      break;
    #endif
    #endif
  }
  #endif
}


//  ------------------------------------------------------------------