/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1991 by Torsten Jürgeleit
 *
 *	Name .....: project.c
 *	Created ..: Sunday 22-Dec-91 21:22:52
 *	Revision .: 1
 *
 *	Date        Author                 Comment
 *	=========   ====================   ====================
 *	22-Apr-91   Torsten Jürgeleit      now for SELECTUP check if
 *                                         SELECTDOWN before
 *	22-Dec-91   Torsten Jürgeleit      Created this file!
 *
 ****************************************************************************
 *
 *	Project part
 *
 * $Revision Header ********************************************************/

	/* Includes */

#include "includes.h"
#include "defines.h"
#include "imports.h"
#include "protos.h"

	/* Defines */

#define MOUSE_BUTTON_SELECT		(1 << 0)
#define MOUSE_BUTTON_MENU		(1 << 1)
#define MOUSE_BUTTON_RUBBER_BAND	(1 << 2)

#define PROJECT_TITLE_REFRESH_DELAY	500000   /* µs */

	/* Perform project action */

   SHORT
perform_project_action(VOID)
{
   struct Box           *box = &current_box;
   struct MsgPort       *up = pwin->UserPort;
   struct IntuiMessage  *msg;
   ULONG seconds, micros, last_seconds, last_micros;
   SHORT status = EDITOR_STATUS_NORMAL;

   while (msg = IGetMsg(up)) {
      struct Template  *tp;
      SHORT mouse_x, mouse_y, snap_x, snap_y;

      /* Get mouse position */
      mouse_x = msg->MouseX;
      mouse_y = msg->MouseY;
      snap_x  = (mouse_x + (snap_offset >> 1)) / snap_offset * snap_offset;
      snap_y  = (mouse_y + (snap_offset >> 1)) / snap_offset * snap_offset;
      switch (msg->Class) {
	 case MOUSEBUTTONS :
	    switch (msg->Code) {
      	       case SELECTDOWN :
		  clear_template_info();
		  switch (editor_mode) {
		     case EDITOR_MODE_CREATE :
			box->bo_X1    = box->bo_X2 = snap_x;
			box->bo_Y1    = box->bo_Y2 = snap_y;
			mouse_button |= MOUSE_BUTTON_RUBBER_BAND;
			draw_box(pwin, box);
			break;

		     case EDITOR_MODE_MODIFY :
			if (select_template_by_pos(mouse_x, mouse_y)) {
			   draw_box(pwin, box);
			   last_snap_x   = snap_x;
			   last_snap_y   = snap_y;
			   modify_mode   = get_modify_mode(mouse_x, mouse_y);
			   mouse_button |= MOUSE_BUTTON_RUBBER_BAND;
			   print_template_info();
			}
			break;

		     case EDITOR_MODE_CLONE :
			if (select_template_by_pos(mouse_x, mouse_y)) {
			   draw_box(pwin, box);
			   last_snap_x   = snap_x;
			   last_snap_y   = snap_y;
			   mouse_button |= MOUSE_BUTTON_RUBBER_BAND;
			   print_template_info();
			}
			break;

		     case EDITOR_MODE_DELETE :
		     case EDITOR_MODE_EDIT :
			if (select_template_by_pos(mouse_x, mouse_y)) {
			   mouse_button |= MOUSE_BUTTON_RUBBER_BAND;
			   print_template_info();
			}
			break;
		  }
		  mouse_button |= MOUSE_BUTTON_SELECT;
		  if (editor_mode != EDITOR_MODE_USE) {
		     print_project_window_title();
		  }
		  break;

	       case SELECTUP :
		  if (mouse_button & MOUSE_BUTTON_SELECT) {
		     tp = selected_template;
		     switch (editor_mode) {
			case EDITOR_MODE_CREATE :
			   if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			      draw_box(pwin, box);
			      box->bo_X2 = snap_x;
			      box->bo_Y2 = snap_y;
			      fix_template_bounds();
			      end_rubber_banding();
			   }
			   break;

			case EDITOR_MODE_MODIFY :
			   if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			      draw_box(pwin, box);
			      clear_template_info();
			      if (tp->tp_Flags & TEMPLATE_FLAG_MODIFIED) {
				 tp->tp_Flags &= ~TEMPLATE_FLAG_MODIFIED;
				 if (mouse_x < 0 || mouse_x > pwin->Width ||
							      mouse_y < 0 ||
						   mouse_y > pwin->Height) {
				    DisplayBeep((LONG)NULL);
				 } else {
				    if (modify_mode == MODIFY_MODE_MOVE) {
				       box->bo_X1 += snap_x - last_snap_x;
				       box->bo_Y1 += snap_y - last_snap_y;
				       box->bo_X2 += snap_x - last_snap_x;
				       box->bo_Y2 += snap_y - last_snap_y;
				    } else {
				       box->bo_X2 += snap_x - last_snap_x;
				       box->bo_Y2 += snap_y - last_snap_y;
				    }
				    fix_template_bounds();
				    end_rubber_banding();
				 }
			      }
			   }
			   break;

			case EDITOR_MODE_CLONE :
			   if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			      draw_box(pwin, box);
			      clear_template_info();
			      if (mouse_x < 0 || mouse_x > pwin->Width ||
				    mouse_y < 0 || mouse_y > pwin->Height) {
				 DisplayBeep((LONG)NULL);
			      } else {
				 box->bo_X1 += snap_x - last_snap_x;
				 box->bo_Y1 += snap_y - last_snap_y;
				 box->bo_X2 += snap_x - last_snap_x;
				 box->bo_Y2 += snap_y - last_snap_y;
				 fix_template_bounds();
				 end_rubber_banding();
			      }
			      tp->tp_Flags &= ~TEMPLATE_FLAG_MODIFIED;
			   }
			   break;

			case EDITOR_MODE_DELETE :
			   if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			      clear_template_info();
			      delete_template(selected_template);
			   }
			   break;

			case EDITOR_MODE_EDIT :
			   if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			      info_template  = NULL;
			      info_displayed = FALSE;
			      status         = EDITOR_STATUS_EDIT;
			   }
			   break;
		     }
		     mouse_button &= ~(MOUSE_BUTTON_SELECT |
						  MOUSE_BUTTON_RUBBER_BAND);
		     if (editor_mode != EDITOR_MODE_USE) {
			print_project_window_title();
			ActivateWindow(ewin);
		     }
		  }
		  break;

	       case MENUDOWN :
		  mouse_button |= MOUSE_BUTTON_MENU;
		  break;

	       case MENUUP :
		  mouse_button &= ~MOUSE_BUTTON_MENU;
		  ActivateWindow(ewin);
		  break;
	    }
	    break;

	 case MOUSEMOVE :
	    if (mouse_button & MOUSE_BUTTON_SELECT) {

	       /* Save time for project title refresh delay while rubberbanding */
	       tp           = selected_template;
	       last_seconds = seconds;
	       last_micros  = micros;
	       seconds      = msg->Seconds;
	       micros       = msg->Micros;
	       switch (editor_mode) {
	          case EDITOR_MODE_CREATE :
		     if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			draw_box(pwin, box);
			box->bo_X2 = snap_x;
			box->bo_Y2 = snap_y;
			last_snap_x = snap_x;
			last_snap_y = snap_y;
			draw_box(pwin, box);
			if (seconds != last_seconds || (micros -
			       last_micros) > PROJECT_TITLE_REFRESH_DELAY) {
			   print_project_window_title();
			}
		     }
		     break;

		  case EDITOR_MODE_MODIFY :
		     if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			draw_box(pwin, box);
			if (modify_mode == MODIFY_MODE_MOVE) {
			   box->bo_X1 += snap_x - last_snap_x;
			   box->bo_Y1 += snap_y - last_snap_y;
			   box->bo_X2 += snap_x - last_snap_x;
			   box->bo_Y2 += snap_y - last_snap_y;
			} else {
			   box->bo_X2 += snap_x - last_snap_x;
			   box->bo_Y2 += snap_y - last_snap_y;
			}
			last_snap_x = snap_x;
			last_snap_y = snap_y;
			draw_box(pwin, box);
			if (seconds != last_seconds || (micros -
			       last_micros) > PROJECT_TITLE_REFRESH_DELAY) {
			   print_project_window_title();
			}
			tp->tp_Flags |= TEMPLATE_FLAG_MODIFIED;
		     }
		     break;

		  case EDITOR_MODE_CLONE :
		     if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			draw_box(pwin, box);
			box->bo_X1 += snap_x - last_snap_x;
			box->bo_Y1 += snap_y - last_snap_y;
			box->bo_X2 += snap_x - last_snap_x;
			box->bo_Y2 += snap_y - last_snap_y;
			last_snap_x = snap_x;
			last_snap_y = snap_y;
			draw_box(pwin, box);
			if (seconds != last_seconds || (micros -
			       last_micros) > PROJECT_TITLE_REFRESH_DELAY) {
			   print_project_window_title();
			}
			tp->tp_Flags |= TEMPLATE_FLAG_MODIFIED;
		     }
		     break;

		  case EDITOR_MODE_DELETE :
		  case EDITOR_MODE_EDIT :
		     if (tp) {

			/* Check if mouse points to selected template */
			if (find_template_by_pos(mouse_x, mouse_y) == tp) {
			   if (!(mouse_button & MOUSE_BUTTON_RUBBER_BAND)) {
			      mouse_button |= MOUSE_BUTTON_RUBBER_BAND;
			      print_template_info();
			      print_project_window_title();
			   }
			} else {
			   if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
			      mouse_button &= ~MOUSE_BUTTON_RUBBER_BAND;
			      clear_template_info();
			      print_project_window_title();
			   }
			}
		     }
		     break;
	       }
	    }
	    break;

	 case NEWSIZE :
	    refresh_all_templates();
	    ActivateWindow(ewin);
	    template_list.tl_Flags |= TEMPLATE_LIST_FLAG_CHANGED;
	    break;
      }
      IReplyMsg(msg);
   }
   return(status);
}
	/* End rubber banding */

   STATIC VOID
end_rubber_banding(VOID)
{
   struct Box  *box = &current_box;
   USHORT type, min_width, min_height, width = box->bo_X2 - box->bo_X1 + 1,
          height = box->bo_Y2 - box->bo_Y1 + 1;

   /* First get current template type */
   if (editor_mode == EDITOR_MODE_CREATE) {
      type = template_type;
   } else {
      type = selected_template->tp_Type;
   }

   /* Now calc minimal dimension required for template */
   switch (type) {
      case TEMPLATE_TYPE_SLIDER :
      case TEMPLATE_TYPE_SCROLLER :
      case TEMPLATE_TYPE_PALETTE :
	 if (width / 2 > height) {
	    min_width  = min_dimension[type].dim_Width;
	    min_height = min_dimension[type].dim_Height;
	 } else {
	    min_width  = min_dimension[type].dim_Height * 2;
	    min_height = min_dimension[type].dim_Width / 2;
	 }
	 break;

      default :
	 min_width  = min_dimension[type].dim_Width;
	 min_height = min_dimension[type].dim_Height;
	 break;
   }

   /* Check template dimension is greater than minimal */
   if (width < min_width || height < min_height) {
      DisplayBeep((LONG)NULL);
   } else {
      struct TemplateList  *tl = &template_list;
      struct Template      *tp;
      struct BorderData    *bd;
      struct TextData      *td;
      struct GadgetData    *gd;

      switch (editor_mode) {
	 case EDITOR_MODE_CREATE :
	    tp = create_template(tl);
	    display_template(tp);
	    break;

	 case EDITOR_MODE_MODIFY :
	    tp = selected_template;
	    CopyMem((BYTE *)box, (BYTE *)
				     &tp->tp_Box, (LONG)sizeof(struct Box));
	    /* Change template dimension */
	    switch (type) {
	       case TEMPLATE_TYPE_BORDER :
		  bd              = &tp->tp_Data.tp_BorderData;
		  bd->bd_LeftEdge = box->bo_X1;
		  bd->bd_TopEdge  = box->bo_Y1;
		  bd->bd_Width    = width;
		  bd->bd_Height   = height;
		  break;

	       case TEMPLATE_TYPE_TEXT :
		  td              = &tp->tp_Data.tp_TextData;
		  td->td_LeftEdge = box->bo_X1;
		  td->td_TopEdge  = box->bo_Y1;

		  /* Calc size of text for template box */
		  box        = &tp->tp_Box;
		  box->bo_X2 = box->bo_X1 + IPrintText(pri, pwin, td->td_Text,
			       td->td_LeftEdge, td->td_TopEdge, td->td_Type,
			      TEXT_DATA_FLAG_NO_PRINT, td->td_TextAttr) - 1;
		  box->bo_Y2 = box->bo_Y1 + td->td_TextAttr->ta_YSize - 1;
		  break;

	       default :
		  gd              = &tp->tp_Data.tp_GadgetData;
		  gd->gd_LeftEdge = box->bo_X1;
		  gd->gd_TopEdge  = box->bo_Y1;
		  gd->gd_Width    = width;
		  gd->gd_Height   = height;
		  switch (gd->gd_Type) {
		     case GADGET_DATA_TYPE_SLIDER :
			if (width / 2 < height) {
			   gd->gd_Flags |= GADGET_DATA_FLAG_ORIENTATION_VERT;
			} else {
			   gd->gd_Flags &= ~GADGET_DATA_FLAG_ORIENTATION_VERT;
			}
			break;

		     case GADGET_DATA_TYPE_SCROLLER :
			if (width / 2 < height) {
			   gd->gd_Flags |= GADGET_DATA_FLAG_ORIENTATION_VERT;
			} else {
			   gd->gd_Flags &= ~GADGET_DATA_FLAG_ORIENTATION_VERT;
			}
			break;

		     case GADGET_DATA_TYPE_PALETTE :
			if (width / 2 < height) {
			   gd->gd_Flags |= GADGET_DATA_FLAG_PALETTE_INDICATOR_TOP;
			} else {
			   gd->gd_Flags &= ~GADGET_DATA_FLAG_PALETTE_INDICATOR_TOP;
			}
			gd->gd_SpecialData.gd_PaletteData.gd_PaletteDepth       = 2;
			gd->gd_SpecialData.gd_PaletteData.gd_PaletteColorOffset = 0;
			gd->gd_SpecialData.gd_PaletteData.gd_PaletteActiveColor = 2;
			break;
		  }
		  break;
	    }
	    refresh_all_templates();
	    break;

	 case EDITOR_MODE_CLONE :
	    tp = clone_template(tl, selected_template, FALSE);
	    display_template(tp);
	    break;
      }
      template_list.tl_Flags |= TEMPLATE_LIST_FLAG_CHANGED;
   }
}
	/* Print project window title */

   VOID
print_project_window_title(VOID)
{
   struct Box  *box = &current_box;
   BYTE   *title = &project_window_title[0];
   USHORT width, height;

   if (box->bo_X2 > box->bo_X1) {
      width = box->bo_X2 - box->bo_X1 + 1;
   } else {
      width = box->bo_X1 - box->bo_X2 + 1;
   }
   if (box->bo_Y2 > box->bo_Y1) {
      height = box->bo_Y2 - box->bo_Y1 + 1;
   } else {
      height = box->bo_Y1 - box->bo_Y2 + 1;
   }
   switch (editor_mode) {
      case EDITOR_MODE_CREATE :
	 if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
	    SPrintf(title, " Left=%d Top=%d Width=%d Height=%d ", 
				     box->bo_X1, box->bo_Y1, width, height);
	 } else {
	    SPrintf(title, " Create %s Template ",
				   template_type_text_array[template_type]);
	 }
	 break;

      case EDITOR_MODE_MODIFY :
	 if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
	    SPrintf(title, " Left=%d Top=%d Width=%d Height=%d ", 
				     box->bo_X1, box->bo_Y1, width, height);
	 } else {
	    strcpy(title, " Modify Template ");
	 }
	 break;

      case EDITOR_MODE_DELETE :
	 if (mouse_button & MOUSE_BUTTON_RUBBER_BAND) {
	    SPrintf(title, " Left=%d Top=%d Width=%d Height=%d ", 
				     box->bo_X1, box->bo_Y1, width, height);
	 } else {
	    strcpy(title, " Delete Template ");
	 }
	 break;

      case EDITOR_MODE_EDIT :
	 strcpy(title, " Edit Template ");
	 break;

      case EDITOR_MODE_USE :
	 strcpy(title, " Use Templates ");
	 break;
   }
   SetWindowTitles(pwin, title, (LONG)NULL);
}
	/* Start a new project */

   SHORT
new_project(struct TemplateList  *tl, USHORT new_flags)
{
   SHORT status;

   /* Free all templates */
   free_template_list(tl);
   ISetGadgetAttributes(egl, EDITOR_GADGET_TEMPLATES, 0L, 0L,
		   USE_CURRENT_VALUE, USE_CURRENT_VALUE, &tl->tl_Templates);
   clear_template_info();

   /* Use default project name? */
   if (new_flags & TEMPLATE_LIST_FLAG_DEFAULT_WINDOW) {
      change_project_name(tl, DEFAULT_PROJECT_NAME, -1);
      strcpy(project_file_requester->fr_File, DEFAULT_PROJECT_FILE_NAME);
   }

   /* Close old project window and open new one */
   if ((status = new_project_window(tl, new_flags)) == EDITOR_STATUS_NORMAL) {
      print_project_window_title();
   }
   return(show_error(status));
}
	/* Close old project window and open new one */

   SHORT
new_project_window(struct TemplateList  *tl, USHORT new_flags)
{
   struct NewWindow  *nwin = &project_new_window;
   USHORT flags;
   SHORT  status;

   /* Use default template list data? */
   if (new_flags & TEMPLATE_LIST_FLAG_DEFAULT_WINDOW) {
      nwin->LeftEdge = 0;
      nwin->TopEdge  = ewin->Height + 1;
      nwin->Width    = wb_screen.Width;
      nwin->Height   = wb_screen.Height - nwin->TopEdge;
      new_flags      = tl->tl_Flags = DEFAULT_TEMPLATE_LIST_FLAGS;
   }

   /* Change render info */
   if (pri) {
      IFreeRenderInfo(pri);
   }
   flags = PROJECT_RENDER_INFO_FLAGS |
				 (new_flags & TEMPLATE_LIST_FLAG_BACK_FILL ?
					   RENDER_INFO_FLAG_BACK_FILL : 0) |
			       (new_flags & TEMPLATE_LIST_FLAG_AVAIL_FONTS ?
					  RENDER_INFO_FLAG_AVAIL_FONTS : 0);
   if (!(pri = IGetRenderInfo((struct Screen *)NULL, flags))) {
      status = EDITOR_ERROR_OUT_OF_MEM;
   } else {

      /* Change new window structure */
      if (new_flags & TEMPLATE_LIST_FLAG_RESIZING) {
	 nwin->Flags |= WINDOWSIZING;
      } else {
	 nwin->Flags &= ~WINDOWSIZING;
      }
      if (new_flags & TEMPLATE_LIST_FLAG_RENDER_COLORS) {
	 flags = (PROJECT_OPEN_WINDOW_FLAGS | OPEN_WINDOW_FLAG_RENDER_PENS);
      } else {
	 nwin->DetailPen = PROJECT_WINDOW_DETAIL_PEN;
	 nwin->BlockPen  = PROJECT_WINDOW_BLOCK_PEN;
	 flags           = PROJECT_OPEN_WINDOW_FLAGS;
      }

      /* Open new project window */
      if (pwin) {
	 ICloseWindow(pwin, FALSE);
      }
      if (!(pwin = IOpenWindow(pri, nwin, flags))) {
	 status = EDITOR_ERROR_NO_WINDOW;
      } else {
	 print_project_window_title();
	 status = EDITOR_STATUS_NORMAL;
      }
   }
   return(show_error(status));
}
	/* Clear project window */

   VOID
clear_project_window(USHORT flags)
{
   SetRast(pwin->RPort, 0L);
   RefreshWindowFrame(pwin);
   if (flags & TEMPLATE_LIST_FLAG_BACK_FILL) {
      IClearWindow(pri, pwin, 0, 0, -1, -1, 0);
   }
}
	/* Change project name and display it as window title */

   VOID
change_project_name(struct TemplateList  *tl, BYTE *new_name, SHORT len)
{
   BYTE *name = &tl->tl_ProjectName[0], *title = &editor_window_title[0];

   if (len < 0) {
      len = strlen(new_name);
   }
   if (len > MAX_PROJECT_NAME_LEN) {
      len = MAX_PROJECT_NAME_LEN;
   }
   strncpy(name, new_name, (size_t)len);
   *(name + len) = '\0';
   SPrintf(title, " %s ", name);
   SetWindowTitles(ewin, title, (BYTE *)-1L);
}
