#define INCL_DOS
#define INCL_WIN
#define INCL_GPI

#include <os2.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <stddef.h>
#include "fm3dll.h"
#include "fm3dlg.h"
#include "fm3str.h"

#pragma data_seg(DATA1)
#pragma alloc_text(NOTIFY,Notify,NotifyWndProc,StartNotify)
#pragma alloc_text(NOTIFY,NotifyThread,NotifyError)
#pragma alloc_text(NOTIFY2,AddNote,NoteThread,NoteWndProc)
#pragma alloc_text(NOTIFY3,StartNotes,EndNote,HideNote,ShowNote)

static HWND hwndNotify;


MRESULT EXPENTRY NotifyWndProc (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2) {

  static ULONG showing = 0;

  switch(msg) {
    case WM_CREATE:
      showing++;
      {
        MRESULT rc;

        rc = PFNWPStatic(hwnd,msg,mp1,mp2);
        if(!WinStartTimer(WinQueryAnchorBlock(hwnd),
                          hwnd,
                          ID_TIMER2,
                          5000)) {
          DosBeep(50,100);
          WinDestroyWindow(hwnd);
        }
        else {

          RGB2 rgb2F,rgb2;

          memset(&rgb2F,0,sizeof(RGB2));
          rgb2F.bRed = 65;
          rgb2.bRed = rgb2.bGreen = rgb2.bBlue = 255;
          rgb2.fcOptions = 0;
          SetPresParams(hwnd,&rgb2,&rgb2F,&rgb2,GetPString(IDS_8HELVTEXT));
          if(hwndMain) {
            if(hwndStatus)
              WinShowWindow(hwndStatus,FALSE);
            if(hwndStatus2)
              WinShowWindow(hwndStatus2,FALSE);
          }
          PostMsg(hwnd,UM_SETUP,MPVOID,MPVOID);
        }
        return rc;
      }

    case UM_SETUP:
      WinSetWindowPos(hwnd,HWND_TOP,0,0,0,0,SWP_ZORDER | SWP_SHOW);
      WinInvalidateRect(hwnd,NULL,FALSE);
      return 0;

    case WM_SETFOCUS:
      if(mp2)
        PostMsg(hwnd,UM_REPLACEFOCUS,mp1,MPVOID);
      break;

    case UM_REPLACEFOCUS:
      if(mp1)
        WinSetFocus(HWND_DESKTOP,(HWND)mp1);
      PostMsg(hwnd,UM_SETUP,MPVOID,MPVOID);
      return 0;

    case WM_PAINT:
      {
        MRESULT mr;
        HPS     hps;
        SWP     swp;
        POINTL  ptl;

        mr = PFNWPStatic(hwnd,msg,mp1,mp2);
        hps = WinGetPS(hwnd);
        if(hps) {
          if(WinQueryWindowPos(hwnd,&swp)) {
            ptl.x = 0;
            ptl.y = 0;
            GpiMove(hps,&ptl);
            GpiSetColor(hps,CLR_RED);
            ptl.x = swp.cx - 1;
            ptl.y = swp.cy - 1;
            GpiBox(hps,DRO_OUTLINE,&ptl,2,2);
          }
          WinReleasePS(hwnd);
        }
        return mr;
      }

    case WM_BUTTON1DOWN:
    case WM_BUTTON2DOWN:
    case WM_BUTTON3DOWN:
    case WM_TIMER:
    case WM_CLOSE:
      WinStopTimer(WinQueryAnchorBlock(hwnd),hwnd,ID_TIMER2);
      WinDestroyWindow(hwnd);
      return 0;

    case WM_DESTROY:
      showing--;
      if(!showing && hwndMain) {
        if(hwndStatus)
          WinShowWindow(hwndStatus,TRUE);
        if(hwndStatus2)
          WinShowWindow(hwndStatus2,TRUE);
      }
      break;
  }
  return PFNWPStatic(hwnd,msg,mp1,mp2);
}


HWND DoNotify (char *str) {

  char          *p;
  HWND          hwnd = (HWND)0,hwndP;
  LONG          x,y,cx,cy;
  SWP           swp,swpS,swpS2;
  static USHORT id = NOTE_FRAME;

  if(str && *str) {
    /* figure out what size the window should be and where it should be */
    hwndP = (hwndMain) ? WinQueryWindow(hwndMain,QW_PARENT) : HWND_DESKTOP;
    WinQueryWindowPos(hwndP,&swp);
    if(hwndStatus)
      WinQueryWindowPos(hwndStatus,&swpS);
    if(hwndStatus2)
      WinQueryWindowPos(hwndStatus2,&swpS2);
    x = (hwndMain) ? ((hwndStatus) ? swpS.x - 1:
          WinQuerySysValue(HWND_DESKTOP,SV_CXSIZEBORDER)) : 0;
    y = (hwndMain) ? ((hwndStatus) ? swpS.y - 1:
          WinQuerySysValue(HWND_DESKTOP,SV_CYSIZEBORDER)) : 0;
    if(hwndMain && hwndStatus) {
      if(hwndStatus2)
        cx = swpS2.cx + swpS.cx + 8;
      else
        cx = swpS.cx + 6;
    }
    else
      cx = (swp.cx - ((x * 2) + 4));
    cy = (hwndMain) ? ((hwndStatus) ? swpS.cy + 2 : 28) : 28;

    /* pretty-up the note by putting on a leading space */
    if(*str != ' ') {
      p = malloc(strlen(str) + 2);
      if(!p)
        p = str;
      else {
        strcpy(p + 1,str);
        *p = ' ';
      }
    }
    else
      p = str;

    hwnd = WinCreateWindow(hwndP,
                           GetPString(IDS_WCERRORWND),
                           p,
                           SS_TEXT | DT_LEFT | DT_VCENTER | WS_VISIBLE,
                           x,
                           y,
                           cx,
                           cy,
                           hwndP,
                           HWND_TOP,
                           id++,
                           NULL,
                           NULL);
    if(p != str)
      free(p);
    if(id > NOTE_MAX)
      id = NOTE_FRAME;
  }

  AddNote(str);

  return hwnd;
}


HWND Notify (char *str) {

  return (HWND)WinSendMsg(MainObjectHwnd,UM_NOTIFY,MPFROMP(str),MPVOID);
}


VOID NotifyError (CHAR *filename,APIRET status) {

  CHAR errortext[512];

  if(!filename)
    return;
  sprintf(errortext,
          GetPString(IDS_ERRORACCESSTEXT),
          status,
          filename);
  if(toupper(*filename) > 'B') {
    if(status == 21)
      strcat(errortext,GetPString(IDS_EMPTYREMOVETEXT));
    else if(status == 27)
      strcat(errortext, GetPString(IDS_CDMUSICTEXT));
    else if(status == 19)
      strcat(errortext,GetPString(IDS_WRITEPROTECTTEXT));
    else if(status == 108)
      strcat(errortext,GetPString(IDS_DRIVELOCKEDTEXT));
  }
  else {
    if(status == 21)
      strcat(errortext,GetPString(IDS_EMPTYFLOPPYTEXT));
    else if(status == 27)
      strcat(errortext,GetPString(IDS_UNFORMATEDTEXT));
    else if(status == 107)
      sprintf(&errortext[strlen(errortext)],
              GetPString(IDS_PHANTOMTEXT),
              toupper(*filename));
    else if(status == 19)
      strcat(errortext,GetPString(IDS_DISKWRITEPROTEXTTEXT));
    else if(status == 108)
      strcat(errortext,GetPString(IDS_DISKLOCKEDTEXT));
  }
  DosBeep(250,10);
  DosBeep(500,10);
  DosBeep(250,10);
  DosBeep(500,10);
  Notify(errortext);
}


MRESULT EXPENTRY NoteWndProc (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2) {

  static HPOINTER hptrIcon = (HPOINTER)0;

  switch(msg) {
    case WM_INITDLG:
      if(hwndNotify != (HWND)0) {
        if(mp2) {
          WinSendDlgItemMsg(hwndNotify,
                            NOTE_LISTBOX,
                            LM_INSERTITEM,
                            MPFROM2SHORT(LIT_END,0),
                            mp2);
          PostMsg(hwndNotify,
                  UM_NOTIFY,
                  MPVOID,
                  MPVOID);
          free((CHAR *)mp2);
        }
        WinDismissDlg(hwnd,0);
        break;
      }
      hwndNotify = hwnd;
      fThreadNotes = FALSE;
      {
        BOOL dummy = TRUE;

        PrfWriteProfileData(fmprof,
                            FM3Str,
                            "ThreadNotes",
                            &dummy,
                            sizeof(BOOL));
      }
      if(mp2) {
        WinSendDlgItemMsg(hwnd,
                          NOTE_LISTBOX,
                          LM_INSERTITEM,
                          MPFROM2SHORT(LIT_END,0),
                          mp2);
        free((CHAR *)mp2);
      }
      {
        HWND hwndActive;

        hwndActive = WinQueryActiveWindow(HWND_DESKTOP);
        PostMsg(hwnd,
                UM_FOCUSME,
                MPFROMLONG(hwndActive),
                MPVOID);
      }
      hptrIcon = WinLoadPointer(HWND_DESKTOP,
                                FM3ModHandle,
                                NOTE_FRAME);
      if(hptrIcon)
        WinDefDlgProc(hwnd,
                      WM_SETICON,
                      MPFROMLONG(hptrIcon),
                      MPFROMLONG(0L));
      break;

    case UM_FOCUSME:
      {
        ULONG size = sizeof(SWP),
              fl = SWP_ZORDER | SWP_FOCUSDEACTIVATE | SWP_SHOW;
        SWP   swp;

        if(PrfQueryProfileData(fmprof,
                               FM3Str,
                               "NoteWndSwp",
                               (PVOID)&swp,
                               &size)) {
          if(swp.fl & (SWP_HIDE | SWP_MINIMIZE)) {
            fl |= SWP_MINIMIZE;
            fl &= (~SWP_SHOW);
          }
          else
            fl |= (SWP_MOVE | SWP_SIZE);
        }
        WinSetWindowPos(hwnd,
                        HWND_BOTTOM,
                        swp.x,
                        swp.y,
                        swp.cx,
                        swp.cy,
                        fl);
        if(fl & SWP_MINIMIZE) {
          WinSetWindowUShort(hwnd,QWS_XRESTORE,(USHORT)swp.x);
          WinSetWindowUShort(hwnd,QWS_CXRESTORE,(USHORT)swp.cx);
          WinSetWindowUShort(hwnd,QWS_YRESTORE,(USHORT)swp.y);
          WinSetWindowUShort(hwnd,QWS_CYRESTORE,(USHORT)swp.cy);
        }
      }
      if(mp1)
        WinSetActiveWindow(HWND_DESKTOP,(HWND)mp1);
      return 0;

    case UM_STRETCH:
      {
        SWP  swp;
        LONG titl,szbx,szby;

        WinQueryWindowPos(hwnd,&swp);
        if(!(swp.fl & (SWP_MINIMIZE | SWP_HIDE))) {
          szbx = SysVal(SV_CXSIZEBORDER);
          szby = SysVal(SV_CYSIZEBORDER);
          titl = SysVal(SV_CYTITLEBAR);
          WinSetWindowPos(WinWindowFromID(hwnd,NOTE_LISTBOX),
                          HWND_TOP,
                          szbx,
                          szby,
                          swp.cx - (szbx * 2L),
                          (swp.cy - titl) - (szby * 2L),
                          SWP_MOVE | SWP_SIZE);
        }
        if(!(swp.fl & SWP_MAXIMIZE)) {
          if(swp.fl & (SWP_MINIMIZE | SWP_HIDE)) {
            swp.x = WinQueryWindowUShort(hwnd,QWS_XRESTORE);
            swp.y = WinQueryWindowUShort(hwnd,QWS_YRESTORE);
            swp.cx = WinQueryWindowUShort(hwnd,QWS_CXRESTORE);
            swp.cy = WinQueryWindowUShort(hwnd,QWS_CYRESTORE);
          }
          PrfWriteProfileData(fmprof,
                              FM3Str,
                              "NoteWndSwp",
                              (PVOID)&swp,
                              sizeof(SWP));
        }
      }
      return 0;

    case WM_ADJUSTWINDOWPOS:
      PostMsg(hwnd,
              UM_STRETCH,
              MPVOID,
              MPVOID);
      break;

    case UM_CONTAINER_FILLED:
      {
        SHORT x,y;

        x = (SHORT)WinSendDlgItemMsg(hwnd,
                                     NOTE_LISTBOX,
                                     LM_QUERYITEMCOUNT,
                                     MPVOID,
                                     MPVOID);
        if(x > 60) {
          for(y = 0;y < x - 50;y++)
            WinSendDlgItemMsg(hwnd,
                              NOTE_LISTBOX,
                              LM_DELETEITEM,
                              MPFROMSHORT(y),
                              MPVOID);
        }
      }
      return 0;

    case UM_NOTIFY:
      {
        SHORT x;

        x = (SHORT)WinSendDlgItemMsg(hwnd,
                                     NOTE_LISTBOX,
                                     LM_QUERYITEMCOUNT,
                                     MPVOID,
                                     MPVOID);
        if(x > 0)
          WinSendDlgItemMsg(hwnd,
                            NOTE_LISTBOX,
                            LM_SETTOPINDEX,
                            MPFROMSHORT(x),
                            MPVOID);
      }
      return 0;

    case UM_SHOWME:
      WinSetWindowPos(hwnd,
                      HWND_TOP,
                      0,
                      0,
                      0,
                      0,
                      SWP_SHOW | SWP_RESTORE | SWP_ZORDER | SWP_ACTIVATE);
      return 0;

    case WM_COMMAND:
      return 0;

    case WM_CLOSE:
      WinDismissDlg(hwnd,0);
      return 0;

    case WM_DESTROY:
      if(hwndNotify == hwnd) {
        fThreadNotes = FALSE;
        PrfWriteProfileData(fmprof,
                            FM3Str,
                            "ThreadNotes",
                            &fThreadNotes,
                            sizeof(BOOL));
        hwndNotify = (HWND)0;
      }
      if(hptrIcon)
        WinDestroyPointer(hptrIcon);
      if(!PostMsg((HWND)0,
                   WM_QUIT,
                   MPVOID,
                   MPVOID))
        WinSendMsg((HWND)0,
                   WM_QUIT,
                   MPVOID,
                   MPVOID);
      break;
  }
  return WinDefDlgProc(hwnd,msg,mp1,mp2);
}


VOID NoteThread (VOID *args) {

  HAB    hab2;
  HMQ    hmq2;

  hab2 = WinInitialize(0);
  if(hab2) {
    hmq2 = WinCreateMsgQueue(hab2,0);
    if(hmq2) {
      if(!hwndNotify)
        WinDlgBox(HWND_DESKTOP,
                  HWND_DESKTOP,
                  NoteWndProc,
                  FM3ModHandle,
                  NOTE_FRAME,
                  (CHAR *)args);
      WinDestroyMsgQueue(hmq2);
    }
    WinTerminate(hab2);
  }
}


BOOL StartNotes (CHAR *note) {

  if(!hwndNotify) {
    if(_beginthread(NoteThread,
                    NULL,
                    65536,
                    (PVOID)note) != -1)
      return TRUE;
  }
  else
    return TRUE;
  return FALSE;
}


BOOL AddNote (CHAR *note) {

  CHAR *s,*p;
  BOOL  once = FALSE,ret = FALSE;

  if((fThreadNotes || hwndNotify) && note && *note) {
    p = note;
    while(*p == ' ')
      p++;
    if(*p) {
      if(!hwndNotify) {
        fThreadNotes = FALSE;
        StartNotes(NULL);
        if(!hwndNotify)
          DosSleep(33L);
        if(!hwndNotify)
          DosSleep(33L);
        if(!hwndNotify)
          DosSleep(33L);
      }
      if(hwndNotify) {
        s = malloc(strlen(p) + 14);
        if(s) {
          sprintf(s,"%08lx  %s",_threadid,p);
          while(!once) {
            if((SHORT)WinSendDlgItemMsg(hwndNotify,
                                        NOTE_LISTBOX,
                                        LM_INSERTITEM,
                                        MPFROM2SHORT(LIT_END,0),
                                        MPFROMP(s)) >= 0) {
              ret = TRUE;
              PostMsg(hwndNotify,
                      UM_NOTIFY,
                      MPVOID,
                      MPVOID);
              break;
            }
            PostMsg(hwndNotify,
                    UM_CONTAINER_FILLED,
                    MPVOID,
                    MPVOID);
            once = TRUE;
          }
        }
        free(s);
      }
    }
  }
  return ret;
}


VOID EndNote (VOID) {

  if(hwndNotify)
    if(!PostMsg(hwndNotify,
                WM_CLOSE,
                MPVOID,
                MPVOID))
      WinSendMsg(hwndNotify,
                 WM_CLOSE,
                 MPVOID,
                 MPVOID);
}


VOID ShowNote (VOID) {

  if(!hwndNotify)
    StartNotes(NULL);
  if(!hwndNotify)
    DosSleep(33L);
  if(!hwndNotify)
    DosSleep(33L);
  if(!hwndNotify)
    DosSleep(33L);
  if(hwndNotify)
    PostMsg(hwndNotify,
            UM_SHOWME,
            MPVOID,
            MPVOID);
}


VOID HideNote (VOID) {

  if(hwndNotify)
    WinSetWindowPos(hwndNotify,
                    HWND_BOTTOM,
                    0,
                    0,
                    0,
                    0,
                    SWP_MINIMIZE | SWP_ZORDER | SWP_FOCUSDEACTIVATE);
}
