/********************************************************************
                         WRAPPARA - by Ricardo García

  Description: Word wraps from cursor to end of paragraph
  Syntax:      WRAPPARA

  If you modify this macro, save it under different name because
  new version of the GWD Text Editor may overwrite it.

  This is a slightly modified version of WORDWRAP (c) 1998 Vedran Gaco.
  All right reserved..

  Since i liked to wrap only certain paragraphs...
********************************************************************/

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <editor/app.h>
#include <editor/doc.h>
#include <editor/options.h>
#include <editor/macros.h>
#include <editor/string.h>


typedef struct _cursorpos {
   long x;
   long y;
} CURSORPOS;

// function prototypes
void WordWrapPara(HDOC);
int isblank(char);
void removetrailingblanks(HDOC);
void joinlinewithspace(HDOC);
/*-------------------------------------------------------------------
                    main function
-------------------------------------------------------------------*/

int main(int argc, char *argv[])
{
   HDOC hdoc;

   hdoc = Gte_GetActiveDocument();
   if(hdoc == NULL) {
      MsgBox("Cannot get handle of the active document!", MB_OK);
      return 1;
   }
   // check if document is read only
   if(Gte_IsReadOnly(hdoc)) {
      MsgBox("Document is read only!", MB_OK);
      return 1;
   }
   // if the document is in the selection and/or line drawing mode, turn them off
   // this is not necessary for this macro, but this is sample macro
   GM_EndSelect(hdoc);
   GM_EndLineDraw(hdoc);

   // check file extension
   {
      char szFileExt[16];

      Gte_GetFileExtension(hdoc, szFileExt, sizeof(szFileExt));
      // if document does not have file ext, empty string will be returned
      if(szFileExt[0] != 0)
      {
         if(stricmp(szFileExt, "c") == 0   || stricmp(szFileExt, "cpp") == 0 ||
            stricmp(szFileExt, "cxx") == 0 || stricmp(szFileExt, "cc") == 0 ||
            stricmp(szFileExt, "h") == 0   || stricmp(szFileExt, "hxx") == 0 ||
            stricmp(szFileExt, "hpp") == 0 || stricmp(szFileExt, "java") == 0 ||
            stricmp(szFileExt, "pas") == 0 || stricmp(szFileExt, "bas") == 0 ||
            stricmp(szFileExt, "for") == 0 || stricmp(szFileExt, "pl") == 0 ||
            stricmp(szFileExt, "clp") == 0) // adding CLIPS source code extension
         {
            if(MsgBox("Word wrap source code, are you sure?", MB_YESNO) != IDYES)
            {
               return 1;
            }
         }
      }
   }

//   if(MsgBox("Word wrap all lines in the active document?",
//      MB_YESNO | MB_ICONQUESTION) == IDYES)
//   {
      // remember cursor position (this is not necessary, but it is user friendly)
      GM_SaveCursorPos(hdoc);
      // to speed up macro disable screen update
      Gte_LockUpdate(hdoc);

      WordWrapPara(hdoc);

      // Unlock screen update and redraw screen if necessary
      Gte_UnlockUpdate(hdoc);
      // restore cursor position from stack
      GM_RestoreCursorPos(hdoc);
      // scroll window if necessary to make cursor visible
      Gte_FixWindowPos(hdoc);
//   }
   return 0;
}

int isblank(char c)
{
  if((c==' ') || (c=='\t')) return 1;
  return 0;
}

void removetrailingblanks(HDOC hdoc)
{
   char curchar;

   GM_LineEnd(hdoc);
   do{
     GM_CursorLeft(hdoc);
     curchar=Gte_GetCurrentChar(hdoc);
   }while (isblank(curchar) && (curchar!=0));
   GM_CursorRight(hdoc);
   GM_DeleteToEOL(hdoc);
}

void joinlinewithspace(HDOC hdoc)
{
   char curchar;
   removetrailingblanks(hdoc); // CM_JoinLine doesn't erase leading blanks
   do{                         // so we have to do everything by hand
     GM_DeleteChar(hdoc); // the first delete does the joining
   }while(isblank(Gte_GetCurrentChar(hdoc))); // then we erase all spaces
                                              // while keeping the cursor pos.
   Gte_InsertText(hdoc," "); // and insert " " in the appropiate position
}

/*-------------------------------------------------------------------
                   WordWrapPara

  Word wrap the current paragraph from cursor
-------------------------------------------------------------------*/

void WordWrapPara(HDOC hdoc)
{
   int  nWordWrapCol;
   int  nextlineempty;
   char *pszLine,*pszNext,curchar;
   long curline,curlinelen;
   long lLine;

   nWordWrapCol = Gte_GetWordWrapCol();

   // reserve memory for line
   pszLine = (char *)malloc(Gte_GetMaxLineLen()+1);
   if(pszLine == NULL) {
      MsgBox("Not enought memory", MB_OK);
      return;
   }
   pszNext = (char *)malloc(Gte_GetMaxLineLen()+1);
   if(pszLine == NULL) {
      MsgBox("Not enought memory", MB_OK);
      free(pszLine);
      return;
   }

   // Show wait mouse cursor (hourglass)
   WaitCursor();

   // for each line in the document (be careful we must always call
   // Gte_GetNumOfLines because number of lines in the document will
   // be probably increased in the loop)
   Gte_GetCursorPos(hdoc, NULL, &curline);
   lLine = curline;
   nextlineempty = 0;
   while ((lLine <= Gte_GetNumberOfLines(hdoc)) && (!nextlineempty))
   {
     curlinelen=Gte_GetLineLen(hdoc,lLine,FALSE);
     while (curlinelen > nWordWrapCol)
     {
        {
          char *psz;
          int  nWrapAtCol = 0; // insert new line at this column pos

          Gte_GetLine(hdoc, lLine, pszLine, Gte_GetMaxLineLen()+1);

          psz = pszLine;
          while(*psz == ' ' || *psz == '\t') psz++;
          while(*psz)
          {
              while(*psz && (*psz != ' ' && *psz != '\t')) psz++;
              if(Gte_GetCharColumnPos(pszLine, psz) > nWordWrapCol && nWrapAtCol > 4)
              {
                  // word wrap
                  Gte_SetCursorPos(hdoc, nWrapAtCol, lLine, FALSE);
                  GM_NewLine(hdoc);
                  //Gte_InsertText(hdoc, "\r\n"); // Autoident will not work
                  break;
              }
              while(*psz == ' ' || *psz == '\t') psz++;
              nWrapAtCol = Gte_GetCharColumnPos(pszLine, psz);
          }
        }
        Gte_GetCursorPos(hdoc, NULL, &lLine);
        curlinelen=Gte_GetLineLen(hdoc,lLine,FALSE);
     }
     if (lLine == Gte_GetNumberOfLines(hdoc))
        nextlineempty=1;
     else
     while ((lLine < Gte_GetNumberOfLines(hdoc)) &&
           (curlinelen<= nWordWrapCol))
     {
       Gte_GetLine(hdoc, lLine+1, pszNext, Gte_GetMaxLineLen()+1);
       if (Gte_StrLenTrim(pszNext)==0)
       {
         nextlineempty = 1;
         break;
       }
       joinlinewithspace(hdoc);
       curlinelen=Gte_GetLineLen(hdoc,lLine,FALSE);
     }
   }

   RestoreCursor();

   free(pszNext);
   free(pszLine);
}