//
//   Headers detail edit for compose
//
//   1/8/96  M.Shimomai
//           Kagoshima Univ., Japan
//
#include <windows.h>
#include <windowsx.h>
#include "wvglob.h"
#include "winvn.h"
#pragma hdrstop
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>

DEF BOOL IsAdditionalHeader(char *line);
char *GetDlgEditText (HWND hDlg, unsigned int iMessage);

BOOL SearchLineTextBlock (TypTextBlock * textBlock, char *prefix);
unsigned long iSearchLineTextBlock (TypTextBlock * textBlock, char *prefix);

/*-- function WinVnHeadersDialog ---------------------------------------
 *
 */
void
ResizeHeaderDialog(HWND hDlg)
{
#define XSPACING		5
#define YSPACING		2

	  HWND hItem;
	  RECT rect;
	  int cx, cy, ySize;
	  SIZE size;
	  HDC hDC;
	  HFONT hOldFont;
	  
	  GetClientRect (hDlg, &rect);
	  cx = RectWidth (rect);
	  cy = RectHeight (rect);
	  ySize = (int) (2 * WinVnLineHeight);
	  hItem = GetDlgItem(hDlg, IDC_HEADER_EDIT);
	  hDC = GetDC(hItem);
	  hOldFont = SelectObject (hDC, hWinVnFont);
	  GetTextExtentPoint (hDC, " Cancel ", 11, &size);
	  SelectObject (hDC, hOldFont);
	  ReleaseDC (hItem, hDC);
	  MoveWindow (hItem, 0, 0, cx, cy - ySize - YSPACING * 3, TRUE);
	  cx = cx / 2;
      SendDlgItemMessage (hDlg, IDC_HEADER_EDIT, WM_SETFONT, (WPARAM) hCompositionFont, FALSE);
	  MoveWindow (GetDlgItem(hDlg, IDOK),
	  			  cx - XSPACING - size.cx, cy - ySize - YSPACING,
	  			  size.cx, ySize, TRUE);
	  SendDlgItemMessage (hDlg, IDOK, WM_SETFONT, (WPARAM) hWinVnFont, TRUE);
	  MoveWindow (GetDlgItem(hDlg, IDCANCEL),
	  			  cx + XSPACING, cy - ySize - YSPACING,
	  			  size.cx, ySize, TRUE);
	  SendDlgItemMessage (hDlg, IDCANCEL, WM_SETFONT, (WPARAM) hWinVnFont, TRUE);
}

char far *newheader;

BOOL FAR PASCAL
WinVnHeadersDlg (HWND hDlg, unsigned int iMessage, WPARAM wParam, LPARAM lParam)
{
  HWND hWnd;
  RECT rect;
  int widthDlg;
  char *ptr;

  switch (iMessage) {
  case WM_INITDIALOG:
    SendDlgItemMessage (hDlg, IDC_HEADER_EDIT, WM_SETFONT, (WPARAM) hCompositionFont, FALSE);
	ptr = (char *) lParam;
	if (ptr && *ptr) {
	  SetDlgItemText (hDlg, IDC_HEADER_EDIT, ptr);
	}
	hWnd = GetParent(hDlg);
	GetClientRect (hWnd, &rect);
	widthDlg = RectWidth (rect);
	GetWindowRect (hDlg, &rect);
	MoveWindow (hDlg, (int)rect.left, (int)rect.top, widthDlg, RectHeight(rect), TRUE);
	ResizeHeaderDialog(hDlg);
	return TRUE;
	break;

  case WM_SIZE:
	ResizeHeaderDialog(hDlg);
	break;

  case WM_COMMAND:
	switch (LOWORD (wParam)) {
	case IDOK:
		if (SendDlgItemMessage (hDlg, IDC_HEADER_EDIT, EM_GETMODIFY, 0, 0L)) {
		  if (!(newheader = GetDlgEditText (hDlg, IDC_HEADER_EDIT))) {
			MessageBox (GetDlgItem(hDlg, IDC_HEADER_EDIT), "Can't retrieve new header part text",
				 "Failed in Headers Detail Dialog", MB_OK);
			EndDialog (hDlg, FALSE);
			break;
		  }
		  EndDialog (hDlg, TRUE);
		}
		else {
		  EndDialog (hDlg, FALSE);
		}
		break;

	case IDCANCEL:
	  EndDialog (hDlg, FALSE);
	  break;

	default:
	  return FALSE;
	}
	break;

  case WM_CHAR:
  	if (LOWORD (wParam) == VK_TAB) {
	  break;
	}
	return FALSE;

  default:
	return FALSE;
	break;
  }
  return TRUE;
}


#define TEXT_SIZE_INC		1024L

void 
EditHeaders (WndEdit * editWnd)
{
  TypTextBlock * headers;
  char *line, *buf;
  unsigned long i;
  long left, num;
  char *ptr, *endPtr, *p, *q;
  int result, n;
  char title[MAXDIALOGSTRING];

  if ((headers = InitTextBlock (editWnd->hWnd)) == NULL)
	return;
  if (GenerateHeadersForSend (editWnd, headers, NULL) == FAIL)
	return;

  left = TEXT_SIZE_INC;
  num = 1;
  if ((buf = (char *) GlobalAllocPtr (GMEM_MOVEABLE,  left * sizeof (char))) == NULL) {
	MessageBox (editWnd->hWnd, "Failed to Generate Article", "Memory Allocation Failure", MB_OK | MB_ICONSTOP);
	return;
  }
  *buf = '\0';

  for (i = 0; i < headers->numLines; i++) {
	line = TextBlockLine (headers, i);
	if ((left -= strlen(line)) < 0) {
      if ((buf = (char *) GlobalReAllocPtr (buf,TEXT_SIZE_INC * (++num) * sizeof (char), GMEM_MOVEABLE)) == NULL) {
	    MessageBox (editWnd->hWnd, "Failed to Generate Article", "Memory Allocation Failure", MB_OK | MB_ICONSTOP);
	    return;
      }
      left += TEXT_SIZE_INC;
    }
    strcat(buf, line);
  }

  FreeTextBlock (headers);

  ContinueEdit:
  if (DialogBoxParam (hInst, "WinVnHeaders", editWnd->hWnd, lpfnWinVnHeadersDlg,
                      (LPARAM) buf) == TRUE) {
    /* now scan text up to a blank line for additional 
     * x- and rfc822 and rfc1036 headers 
     */
	ptr = p = newheader;
	result = SUCCESS;
	while (*p) {
	  if ((endPtr = strchr (p, '\r')) == NULL) {
		endPtr = ptr + strlen(ptr);	/* handle no crlf on last line */
	  } else {
		endPtr++;				/* move past \r */
		/* handle soft line break \r\r\n (see EM_FMTLINES) */
		if (*endPtr == '\r') {
			endPtr++;			/* move past \n */
		}
		if (*endPtr == '\n') {
			endPtr++;			/* move past extra \n (in case of soft line break extra \n */
		}
	  }
	  if (*ptr == '\0') break;	/* blank line */
	  if (isspace(*endPtr)) {
		p = endPtr;
		continue;
	  }	
	  if (!IsAdditionalHeader(ptr)) {		/* not recognized */
		*buf = '\"';
		for(p=ptr, q=buf + 1; *p != ':'; q++, p++) *q = *p;
		*q++ = '\"'; *q = '\0';
		strcat(buf, " : non RFC822/RFC1036 header.\nBack to header part edit window.");
	    if(MessageBox (editWnd->hWnd, buf, "Warning: Not recognized header", MB_YESNO)
	       == IDYES) {
		  GlobalFreePtr (buf);
		  buf = newheader;
		  goto ContinueEdit;
		}
	  }
	  ptr = p = endPtr;
	}

	ResetTextBlock(editWnd->extraHeaders);
	ptr = p = newheader;
	while (*p && result == SUCCESS) {
	  if ((endPtr = strchr (p, '\r')) == NULL) {
		endPtr = ptr + strlen(ptr);	/* handle no crlf on last line */
	  } else {
		q = endPtr;
//		*endPtr = '\0';
		endPtr++;				/* move past \r */
		/* handle soft line break \r\r\n (see EM_FMTLINES) */
		if (*endPtr == '\r') {
			endPtr++;			/* move past \n */
		}
		if (*endPtr == '\n') {
			endPtr++;			/* move past extra \n (in case of soft line break extra \n */
		}
	  }
	  if (*ptr == '\0') break;	/* blank line */
	  if (isspace(*endPtr)) {	/* continuous line */
		p = endPtr;
		continue;
	  }	
	  else
	  	*q = '\0';

	  for (n = 0; n < HDR_NUM_CONTROLS; n++) {
		if (n == HDR_ATTACH)
		  continue;

		if (editWnd->headerControls->UI[n]) {
		  SendMessage (editWnd->headerControls->title[n], WM_GETTEXT, (WPARAM) MAXDIALOGSTRING, (LPARAM) (LPCSTR) title);
		  if (_strnicmp(title, ptr, strlen(title)) == 0) {
			SendMessage (editWnd->headerControls->UI[n], WM_SETTEXT, (WPARAM) MAXHEADERLINE, (LPARAM) (LPCSTR) (strchr (ptr, ':') + 2));
			break;
		  }
		}
	  }
	  if (n >= HDR_NUM_CONTROLS) {
		unsigned long i;
		char prefix[32];
		strncpy(prefix, ptr, 31);
		prefix[31] = '\0';
		if (p = strchr(prefix, ':'))
			*(++p) = '\0';
		_snprintf(buf, MAXHEADERLINE, "%s\r\n", ptr);
		if ((i = iSearchLineTextBlock(editWnd->extraHeaders, prefix))
			< editWnd->extraHeaders->numLines) {
		  result = ReplaceLineInTextBlock (editWnd->extraHeaders, i, buf);
		}
		else {
	  	  result = AddLineToTextBlock (editWnd->extraHeaders, buf);
		}
	  }
	  ptr = p = endPtr;
	}

	GlobalFreePtr (newheader);
    GlobalFreePtr (buf);

    if ((buf = GetEditText(editWnd->hWndEdit)) && editWnd->bodyOffset > 0L) {
        SetWindowText (editWnd->hWndEdit, &(buf[editWnd->bodyOffset]));
        editWnd->bodyOffset = 0L;
    }
  }
  GlobalFreePtr (buf);
}


unsigned long
iSearchLineTextBlock (TypTextBlock * textBlock, char *prefix)
{
  unsigned long i;

  for (i=0; i < textBlock->numLines; i++)
	if (_strnicmp(prefix, TextBlockLine(textBlock, i), strlen(prefix))==0) {
	  break;
	}
  return (i);
}

BOOL
SearchLineTextBlock (TypTextBlock * textBlock, char *prefix)
{
  if (textBlock == NULL) return (FALSE);
  return (iSearchLineTextBlock(textBlock, prefix) < textBlock->numLines);
}

BOOL
GetHeaderLineTextBlock (char *content, TypTextBlock * textBlock, char *prefix)
{
  unsigned long i;
  char *p;
  if (textBlock &&
      (i=iSearchLineTextBlock(textBlock, prefix)) < textBlock->numLines) {
	strcpy(content, TextBlockLine(textBlock, i) + strlen(prefix) + 1);
	for (p = content + strlen(content) - 1;
		 p > content && (*p == '\r' || *p == '\n') ; p--) *p = '\0';
	*(TextBlockLine(textBlock, i)) = '\0';
	return (TRUE);
  }
  return (FALSE);
}


BOOL
ReconstructTextBlock (HWND hParentWnd, TypTextBlock **textBlock)
{
  TypTextBlock * headers;
  char *p;
  unsigned long i;
  int result = SUCCESS;

  if (*textBlock) {
	headers = InitTextBlock (hParentWnd);
	for (i=0; i < (*textBlock)->numLines && result == SUCCESS; i++) {
	  if(p = TextBlockLine((*textBlock), i))
		result = AddLineToTextBlock (headers, p);
	}
	if (result == SUCCESS) {
	  FreeTextBlock (*textBlock);
	  *textBlock = headers;
	}
  }
  return (result);
}

char *
GetDlgEditText (HWND hDlg, unsigned int iMessage)
{
  unsigned int size;
  char *newText;

#define EDIT_PAD 2

  size = (unsigned int) SendDlgItemMessage (hDlg, iMessage, WM_GETTEXTLENGTH, 0, 0L)
                 + EDIT_PAD;

  if ((newText = (char *) GlobalAllocPtr (GMEM_MOVEABLE, size * sizeof (char))) == NULL) {
        MessageBox (hDlg, "Memory allocation failure", "Edit Text", MB_OK);
        return (NULL);
  }
  *newText = '\0';

  if (GetDlgItemText (hDlg, iMessage, (LPSTR) newText, size) == 0) {
        MessageBox (hDlg, "Can't get text", "Edit Text", MB_OK);
        return (NULL);
  }

  return (newText);
  }

