/***************************************
 *************   notes.c   *************
 ***************************************/

#include <dos/dos.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/dos_protos.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "stickit.h"

#include "consts.h"
#include "structs.h"
#include "prototype.h"

extern prjptr prj;

struct EasyStruct reqnonotes =
   {
   sizeof(struct EasyStruct),
   0,
   "StickIt",
   "No notes to display",
   "Continue"
   };

void shownotes()
   {
   struct IntuiMessage *nextmessage;

   nteptr currnote = NULL;
   struct ndnode *ndptr;

   int done = FALSE;

   /***   Create message port   ***/

   prj->msgport = CreateMsgPort();

   if (!prj->msgport)
      error("Can't create message port",ERR_MSGPORT);

   prj->no_notes_visable = 0;

   opennotes();

   if (prj->no_notes_visable == 0)
      {
      EasyRequest(NULL,&reqnonotes,NULL);

      /***   Remove message port   ***/

      DeleteMsgPort(prj->msgport);
      prj->msgport = NULL;

      prj->editnotes = TRUE;
      return;
      }

   refreshnotes();

   /***   Answer messages   ***/

   while (!done)
      {
      Wait (1 << prj->msgport->mp_SigBit);
          
      while (nextmessage = (struct IntuiMessage *)GetMsg(prj->msgport))
         {
         prj->currmessage.Code = nextmessage->Code;
         prj->currmessage.Class = nextmessage->Class;
         prj->currmessage.IDCMPWindow = nextmessage->IDCMPWindow;
         prj->currmessage.Seconds = nextmessage->Seconds;
         prj->currmessage.Micros = nextmessage->Micros;

         ReplyMsg ((struct Message *)nextmessage);

         ndptr = findnodefromwin(prj->currmessage.IDCMPWindow);

         currnote = ndptr->data;

         switch(prj->currmessage.Class)
            {
            case IDCMP_MOUSEBUTTONS:
               switch (prj->currmessage.Code)
                  {
                  case SELECTDOWN:
                     if (DoubleClick(currnote->leftseconds,currnote->leftmicros,
                        prj->currmessage.Seconds,prj->currmessage.Micros))
                        {
                        removenote(ndptr);

                        currnote->show = FALSE;
                        }
                     else
                        {
                        currnote->leftseconds = prj->currmessage.Seconds;
                        currnote->leftmicros =  prj->currmessage.Micros;
                        currnote->rightseconds = 0;
                        currnote->rightmicros = 0;
                        }
                     break;
                  case MENUUP:
                     prj->editnotes = TRUE;
                     done = TRUE;
                     break;
                  default:
                     break;
                  }
               break;
            case IDCMP_REFRESHWINDOW:
               BeginRefresh(prj->currmessage.IDCMPWindow);
               refreshnote(ndptr);
               EndRefresh(prj->currmessage.IDCMPWindow,TRUE);
               break;
            case IDCMP_CHANGEWINDOW:
               currnote->xpos = (int)prj->currmessage.IDCMPWindow->LeftEdge;
               currnote->ypos = (int)prj->currmessage.IDCMPWindow->TopEdge;
               break;
            case IDCMP_VANILLAKEY:
               switch (prj->currmessage.Code)
                  {
                  case 'F':
                  case 'f':
                     WindowToFront(prj->currmessage.IDCMPWindow);
                     break;
                  case 'B':
                  case 'b':
                     WindowToBack(prj->currmessage.IDCMPWindow);
                     break;
                  case 'E':
                  case 'e':
                     prj->editnotes = TRUE;
                     done = TRUE;
                     break;
                  case 'H':
                  case 'h':
                     removenote(ndptr);
                     currnote->show = FALSE;
                     break;
                  }
               break;
            default:
               break;
            }
         }
      if (prj->no_notes_visable == 0)
         {
         prj->editnotes = TRUE;
         done = TRUE;
         }
      }

   /***   Remove note that we clicked on first   ***/

   removenote(ndptr);

   removenotes();

   /***   Remove message port   ***/

   DeleteMsgPort(prj->msgport);
   prj->msgport = NULL;

   /***  Set current note to the last one we clicked on   ***/

   prj->currnode = ndptr;
   }

void opennotes()
   {
   struct ndnode *ndptr;
   nteptr currnote;

   /***   Open all windows, draw back to front   ***/

   ndptr = prj->notes_end->prev;

   while (ndptr->prev)
      {
      currnote = ndptr->data;

      if (currnote->show)
         {
         currnote->win = OpenWindowTags( NULL,
            WA_Left,        currnote->xpos,
            WA_Top,         currnote->ypos,
            WA_Width,       prj->notewidth,
            WA_Height,      prj->noteheight,
            WA_IDCMP,       NULL,
            WA_Flags,       WFLG_DRAGBAR|WFLG_DEPTHGADGET|
                  WFLG_SIMPLE_REFRESH|WFLG_RMBTRAP,
            WA_Title,       currnote->title,
            WA_ScreenTitle, "StickIt V1.03 15th November '93 ©1993 Andy Dean",
                  TAG_DONE );

         if (!currnote->win)
            error("opennotes; Can't open note",ERR_FATAL);

         /***   Must connect window to message port   ***/

         currnote->win->UserPort = prj->msgport;
         ModifyIDCMP(currnote->win,IDCMP_REFRESHWINDOW|IDCMP_VANILLAKEY|
                        IDCMP_MOUSEBUTTONS|IDCMP_CHANGEWINDOW);

         /***   Set font to user's choice   ***/

         SetFont(currnote->win->RPort,prj->notefontptr);

         /***   Reset DoubleClick info   ***/

         currnote->leftseconds = currnote->leftmicros = 0;
         currnote->rightseconds = currnote->rightmicros = 0;

         /***   Clear the note   ***/

         SetAPen(currnote->win->RPort,prj->backcolour);
         RectFill(currnote->win->RPort,(LONG)currnote->win->BorderLeft,
            (LONG)currnote->win->BorderTop,
            currnote->win->Width - (currnote->win->BorderRight + 1),
            currnote->win->Height - (currnote->win->BorderBottom + 1));
         SetAPen(currnote->win->RPort,prj->textcolour);

         /***   Increment note count   ***/

         prj->no_notes_visable++;
         }
      else
         currnote->win = NULL;

      ndptr = ndptr->prev;
      }
   }

void refreshnotes()
   {
   struct ndnode *ndptr;
   nteptr currnote;

   /***   Refresh the text in each window   ***/

   ndptr = prj->notes_start->next;
          
   while (ndptr->next)
      {
      currnote = ndptr->data;

      refreshnote(ndptr);

      ndptr = ndptr->next;
      }
   }

void removenotes()
   {
   struct ndnode *ndptr;
   nteptr currnote;

   /***   Remove all open notes and remove shared message port   ***/
   /***   and close font                                         ***/

   ndptr = prj->notes_start->next;

   while (ndptr->next)
      {
      currnote = ndptr->data;

      removenote(ndptr);

      ndptr = ndptr->next;
      }
   }

void removenote(struct ndnode *ndptr)
   {
   nteptr currnote;

   currnote = ndptr->data;

   if (currnote->win)
      {
      CloseWindowSafely(currnote->win);
      currnote->win = NULL;

      prj->no_notes_visable--;
      }
   }

void refreshnote(struct ndnode *ndptr)
   {
   struct Window *w;
   struct TextFont *myfont;
   struct RastPort *myrp;
   struct TextExtent resultextent;

   nteptr currnote;

   LONG fit,count = 0,printable,l;
   UWORD wtbarheight;

   currnote = ndptr->data;

   if (!currnote->win)   /* Old refresh message */
      return;

   if (!currnote->show)
      return;

   /***   Clear the note   ***/

   SetAPen(currnote->win->RPort,prj->backcolour);
   RectFill(currnote->win->RPort,(LONG)currnote->win->BorderLeft,
      (LONG)currnote->win->BorderTop,
      currnote->win->Width - (currnote->win->BorderRight + 1),
      currnote->win->Height - (currnote->win->BorderBottom + 1));
   SetAPen(currnote->win->RPort,prj->textcolour);

   /***   Blatently nick Commodore's text routines !   ***/

   w = currnote->win;
   myfont = prj->notefontptr;
   myrp = currnote->win->RPort;

   wtbarheight = w->WScreen->BarHeight + myfont->tf_Baseline + 2;

   SetDrMd(myrp,JAM1);
   SetBPen(myrp,prj->backcolour);

   Move(myrp,w->WScreen->WBorLeft,wtbarheight);

   /***   Emulate the Commodore code   ***/

   printable = strlen(currnote->note);

   while (count < printable)
      {
      fit = TextFit(myrp,&(currnote->note[count]),
         (printable - count), &resultextent,
         NULL, 1, 
         (w->Width - (myrp->cp_x + w->BorderLeft +
         w->BorderRight)), myfont->tf_YSize + 1);

      if (fit == 0)
         Move (myrp,w->BorderLeft,myrp->cp_y +
            myfont->tf_YSize + 1);
      else
         {
         if ((fit + count) != printable)   /* Need to wrap */
            {
            for (l = count + fit; ((l > count) &&
               (currnote->note[l] != ' ')); l--);

            if ((l - count) != 0) /* If can't wrap */
               fit = l - count + 1;
            }

         Text(myrp,&(currnote->note[count]),fit);
         count += fit;

         /***  Strip space from start of line   ***/

         while ((count <= printable) &&
            (currnote->note[count] == ' '))
            count++;

         /***  Newline   ***/

         Move (myrp,w->BorderLeft,myrp->cp_y +
            myfont->tf_YSize + 1);
         }

      if (myrp->cp_y > (w->Height - (w->BorderBottom + 2)))
         return;   /* Reached bottom */
      }
   }


struct ndnode *findnodefromwin(struct Window *win)
   {
   struct ndnode *ndptr;
   nteptr currnote;

   ndptr = prj->notes_start->next;
          
   while (ndptr->next)
      {
      currnote = ndptr->data;

      if (currnote->win == win)
         return(ndptr);

      ndptr = ndptr->next;
      }

   return (NULL);
   }


