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

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1999 Alexander Batalov
//  Copyright (C) 1999-2000 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$
//  ------------------------------------------------------------------
//  Some os2 pm func.
//  ------------------------------------------------------------------

#include <gstrall.h>
#include <gmemdbg.h>
#include <gutlos.h>

#define INCL_DOSMODULEMGR
#define INCL_WINWINDOWMGR
#define INCL_DOSPROCESS
#define INCL_WIN
#define INCL_OS2MM
#define INCL_WINFRAMEMGR
#include <os2.h>
#include <os2me.h>

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

HAB      APIENTRY (*pfnWinInitialize)(ULONG);
BOOL     APIENTRY (*pfnWinTerminate)(HAB);
HMQ      APIENTRY (*pfnWinCreateMsgQueue)(HAB, LONG);
BOOL     APIENTRY (*pfnWinDestroyMsgQueue)(HMQ);
BOOL     APIENTRY (*pfnWinEmptyClipbrd)(HAB);
BOOL     APIENTRY (*pfnWinOpenClipbrd)(HAB);
BOOL     APIENTRY (*pfnWinCloseClipbrd)(HAB);
BOOL     APIENTRY (*pfnWinSetClipbrdData)(HAB, ULONG, ULONG, ULONG);
ULONG    APIENTRY (*pfnWinQueryClipbrdData)(HAB, ULONG);
ULONG    APIENTRY (*pfnWinChangeSwitchEntry)(HSWITCH, SWCNTRL *);
BOOL     APIENTRY (*pfnWinSetWindowText)(HWND, PSZ);
BOOL     APIENTRY (*pfnWinQueryClipbrdFmtInfo)(HAB, ULONG, PULONG);
ULONG    APIENTRY (*pfnWinQuerySwitchEntry)(HSWITCH, PSWCNTRL);
HSWITCH  APIENTRY (*pfnWinQuerySwitchHandle)(HWND, PID);
LONG     APIENTRY (*pfnWinQueryWindowText)(HWND, LONG, char *);
MRESULT  APIENTRY (*pfnWinSendMsg)(HWND, ULONG, MPARAM, MPARAM);
HPOINTER APIENTRY (*pfnWinLoadPointer)(HWND, HMODULE, ULONG);
BOOL     APIENTRY (*pfnWinInvalidateRect)(HWND, PRECTL, BOOL);
DWORD    APIENTRY (*pfnmciSendString)(LPSTR, LPSTR, WORD, HWND, WORD);
DWORD    APIENTRY (*pfnmciGetErrorString)(DWORD, LPSTR, WORD);

static BOOL       access_pm_clipboard(void);
static void       leave_pm_clipboard(int mode);


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

HAB               ge_os2_hab = 0;
HMQ               ge_os2_hmq = 0;
HSWITCH           ge_os2_hsw = 0;
HWND              ge_os2_hwndframe = 0;
HMODULE           ge_os2_hmte = 0;
HMODULE           ge_os2_hmte2 = 0;
HMODULE           ge_os2_mdmHandle = 0;
SWCNTRL           ge_os2_swolddata;
SWCNTRL           ge_os2_swdata;
SZ                ge_os2_loaderr[256];
char              ge_os2_coldtitle[GMAXTITLE+1] = "";
HPOINTER          ge_os2_coldicon;
char              ge_os2_title[GMAXTITLE+1] = "";
int               ge_os2_ext_title;
ULONG             ge_os2_oldicon;


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

static struct {
  PPIB ppib;
  HAB hab;
  HMQ hmq;
  ULONG savedtype;
  BOOL opened;
} pminfo;


//  ------------------------------------------------------------------
// Init os/2 pm functions

int g_init_os(int flags) {

  int rc;
  PTIB ptib;
  const char *env;

  memset(&pminfo, 0, sizeof (pminfo));

  DosGetInfoBlocks(&ptib, &pminfo.ppib);
  pminfo.savedtype = pminfo.ppib->pib_ultype;

  // Check PMWIN environment variable, if it set to NO do not try to use
  // PMWIN functions
  if(((env = getenv("PMWIN")) != NULL) and strieql(env, "NO")) {
    rc = 1;
  }
  else {
    // Morph application into PM
    rc = DosQueryModuleHandle((PSZ)"PMWIN", &ge_os2_hmte);
  }

  if(not rc) {
    pminfo.ppib->pib_ultype = 3;
    rc = DosLoadModule((PSZ)ge_os2_loaderr, sizeof(ge_os2_loaderr), (PSZ)"PMWIN", &ge_os2_hmte);
    if(rc)
      return 1;

    // Load the functions dinamically
    rc = DosQueryProcAddr(ge_os2_hmte, 707, 0, (PFN*)&pfnWinCloseClipbrd);
    rc = DosQueryProcAddr(ge_os2_hmte, 716, 0, (PFN*)&pfnWinCreateMsgQueue);
    rc = DosQueryProcAddr(ge_os2_hmte, 726, 0, (PFN*)&pfnWinDestroyMsgQueue);
    rc = DosQueryProcAddr(ge_os2_hmte, 733, 0, (PFN*)&pfnWinEmptyClipbrd);
    rc = DosQueryProcAddr(ge_os2_hmte, 763, 0, (PFN*)&pfnWinInitialize);
    rc = DosQueryProcAddr(ge_os2_hmte, 793, 0, (PFN*)&pfnWinOpenClipbrd);
    rc = DosQueryProcAddr(ge_os2_hmte, 806, 0, (PFN*)&pfnWinQueryClipbrdData);
    rc = DosQueryProcAddr(ge_os2_hmte, 807, 0, (PFN*)&pfnWinQueryClipbrdFmtInfo);
    rc = DosQueryProcAddr(ge_os2_hmte, 854, 0, (PFN*)&pfnWinSetClipbrdData);
    rc = DosQueryProcAddr(ge_os2_hmte, 888, 0, (PFN*)&pfnWinTerminate);
    rc = DosQueryProcAddr(ge_os2_hmte, 841, 0, (PFN*)&pfnWinQueryWindowText);
    rc = DosQueryProcAddr(ge_os2_hmte, 877, 0, (PFN*)&pfnWinSetWindowText);
    rc = DosQueryProcAddr(ge_os2_hmte, 920, 0, (PFN*)&pfnWinSendMsg);
    rc = DosQueryProcAddr(ge_os2_hmte, 780, 0, (PFN*)&pfnWinLoadPointer);
    rc = DosQueryProcAddr(ge_os2_hmte, 765, 0, (PFN*)&pfnWinInvalidateRect);

    rc = DosQueryModuleHandle((PSZ)"PMSHAPI", &ge_os2_hmte2);
    if(rc)
      return 1;
    rc = DosLoadModule((PSZ)ge_os2_loaderr, sizeof(ge_os2_loaderr), (PSZ)"PMSHAPI", &ge_os2_hmte2);
    if(rc)
      return 1;
    DosQueryProcAddr(ge_os2_hmte2, 123, 0, (PFN*)&pfnWinChangeSwitchEntry);
    DosQueryProcAddr(ge_os2_hmte2, 124, 0, (PFN*)&pfnWinQuerySwitchEntry);
    DosQueryProcAddr(ge_os2_hmte2, 125, 0, (PFN*)&pfnWinQuerySwitchHandle);

    if(flags & 1) {
      rc = DosQueryModuleHandle((PSZ)"MDM", &ge_os2_hmte);
      if(not rc) {
        rc = DosLoadModule((PSZ)ge_os2_loaderr, sizeof(ge_os2_loaderr), (PSZ)"MDM", &ge_os2_mdmHandle);
        if(not rc) {
          DosQueryProcAddr(ge_os2_mdmHandle, 0, (PSZ)"mciSendString", (PFN*)&pfnmciSendString);
          DosQueryProcAddr(ge_os2_mdmHandle, 0, (PSZ)"mciGetErrorString", (PFN*)&pfnmciGetErrorString);
        }
      }
    }

    // Make queue
    ge_os2_hab = pfnWinInitialize(0);
    ge_os2_hmq = pfnWinCreateMsgQueue(ge_os2_hab, 0);

    // Find our hSw
    ge_os2_hsw = pfnWinQuerySwitchHandle(0, pminfo.ppib->pib_ulpid);
    if(ge_os2_hsw) {
      pfnWinQuerySwitchEntry(ge_os2_hsw, &ge_os2_swolddata);
      ge_os2_swdata = ge_os2_swolddata;
      ge_os2_hwndframe = ge_os2_swdata.hwnd;
      pfnWinQueryWindowText(ge_os2_hwndframe, sizeof(ge_os2_coldtitle), ge_os2_coldtitle);
    }
  }
  DosSetPriority(PRTYS_PROCESS, PRTYC_REGULAR, PRTYD_MINIMUM, 0);
  return 0;
}


//  ------------------------------------------------------------------
// deInit os/2 pm functions

void g_deinit_os(void) {

  if(ge_os2_hwndframe) {
    pfnWinChangeSwitchEntry(ge_os2_hsw, &ge_os2_swolddata);
    g_set_ostitle(ge_os2_coldtitle);
    pfnWinSendMsg(ge_os2_hwndframe, WM_SETICON, (MPARAM) ge_os2_swolddata.hwndIcon, (MPARAM) 0);
  }
  if(ge_os2_hmq)
    pfnWinDestroyMsgQueue(ge_os2_hmq);
  if(ge_os2_hab)
    pfnWinTerminate(ge_os2_hab);
  if(ge_os2_hmte)
    DosFreeModule(ge_os2_hmte);
  if(ge_os2_hmte2)
    DosFreeModule(ge_os2_hmte2);
  if(ge_os2_mdmHandle)
    DosFreeModule(ge_os2_mdmHandle);
}


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

void g_init_title(char *tasktitle, int titlestatus) {

  strxcpy(ge_os2_title, tasktitle, GMAXTITLE);
  ge_os2_ext_title = titlestatus;
}


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

void g_increase_priority(void) {

  DosSetPriority(PRTYS_PROCESS, PRTYC_REGULAR, PRTYD_MAXIMUM, 0);
}


//  ------------------------------------------------------------------
// Change title

void g_set_ostitle(char *title) {

  if(ge_os2_hsw and ge_os2_hwndframe) {
    strxcpy(ge_os2_swdata.szSwtitle, title, MAXNAMEL);
    pfnWinChangeSwitchEntry(ge_os2_hsw, &ge_os2_swdata);
    pfnWinSetWindowText(ge_os2_hwndframe, (PSZ)title);
  }
}


//  ------------------------------------------------------------------
// Change icon

void g_set_osicon(void) {

  if(ge_os2_hwndframe and ge_os2_hsw) {
    ULONG ulPicture = (ULONG) pfnWinLoadPointer(HWND_DESKTOP, 0, 1);
    if(ulPicture) {
      pfnWinSendMsg(ge_os2_hwndframe, WM_SETICON, (MPARAM) ulPicture, (MPARAM) 0);
      pfnWinInvalidateRect(ge_os2_hwndframe, 0, 1);
      pfnWinChangeSwitchEntry(ge_os2_hsw, &ge_os2_swdata);
    }
  }
}


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

bool g_is_clip_available(void) {

  return make_bool(ge_os2_hab);
}


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

char *g_get_clip_text(void) {

  char *text = NULL;
  char *cd = NULL;
  BOOL clip_open = false;
  if(ge_os2_hab) {
    if((clip_open = access_pm_clipboard()) != true)
      return NULL;
    if((text = (char *) pfnWinQueryClipbrdData(ge_os2_hab, CF_TEXT)) != NULL)
      cd = throw_strdup(text);
    leave_pm_clipboard(clip_open);
  }
  return cd;
}


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

void g_get_ostitle_name(char *currtitle) {

  if(ge_os2_hwndframe)
    pfnWinQueryWindowText(ge_os2_hwndframe, GMAXTITLE, currtitle);
}


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

void g_set_ostitle_name(char *title, int mode) {

  if(mode == 0) {
    char fulltitle[GMAXTITLE+1];
    strcpy(fulltitle, ge_os2_title);
    if(ge_os2_ext_title) {
      int len = strlen(fulltitle);
      if(len < GMAXTITLE-3) {
        if(len)
          strcat(fulltitle, " - ");
        strxcpy(fulltitle+len+3, title, GMAXTITLE-len-3);
      }
    }
    g_set_ostitle(fulltitle);
  }
  else
    g_set_ostitle(title);
}


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

static BOOL access_pm_clipboard(void) {

  BOOL clip_opened = false;
  if(pfnWinOpenClipbrd(ge_os2_hab) == true)
    clip_opened = true;
  else
    leave_pm_clipboard(clip_opened);
  return clip_opened;
}


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

static void leave_pm_clipboard(int mode) {

  if(mode == true)
    pfnWinCloseClipbrd(ge_os2_hab);
}


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

int g_put_clip_text(const char *cd) {

  ULONG len;
  void *text;
  int rc = -1;
  BOOL clip_open = false;
  if(ge_os2_hab) {
    if((clip_open = access_pm_clipboard()) != true)
      return rc;
    pfnWinEmptyClipbrd(ge_os2_hab);
    len = strlen(cd);

    if(len) {
      DosAllocSharedMem((void **) &text, 0, len + 1, PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE);
      strxcpy((char *) text, cd, len + 1);
      if(pfnWinSetClipbrdData(ge_os2_hab, (ULONG) text, CF_TEXT, CFI_POINTER))
        rc = 0;
    }
    leave_pm_clipboard(clip_open);
  }
  return rc;
}


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