/* Copyright 1997 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/***************************************************/
/* File   : DragBox.c                              */
/*                                                 */
/* Purpose: Plot user drag boxes for such things   */
/*          as non-solid frame resizes (where the  */
/*          'box' shape could be very irregular).  */
/*                                                 */
/* Author : A.D.Hodgkinson                         */
/*                                                 */
/* History: 26-Aug-97: Created, based on the ResEd */
/*                     'Common.c.wimp' code.       */
/***************************************************/

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

#include "swis.h"

#include "wimp.h"
#include "wimplib.h"
#include "event.h"

#include "svcprint.h"
#include "Global.h"
#include "FromROSLib.h"
#include "Utils.h"

#include "DragBox.h"

/* Local statics */

/* These are the possible patterns used to plot the drag boxes.      */
/* The first patterns are used when plotting and erasing a drag box. */
/* The second patterns are used when rotating a stationary drag box. */

static char patterns1[] = { 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f, 0x7e };
static char patterns2[] = { 0x82, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x41 };

/* Contain the current patterns */

static int  patternid   = 7; /* Chooses the pattern */
static char pattern1[]  = { 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e };
static char pattern2[]  = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 };

/* This points to the pattern used by dragbox_plot_eor_box; it addresses */
/* pattern1 whilst removing an existing drag box, or plotting a new one, */
/* and addresses pattern2 when rotating a stationary drag box.           */

static char * pattern = pattern1;

/*************************************************/
/* dragbox_set_dotdash()                         */
/*                                               */
/* Sets the dot-dash pattern according to the    */
/* given eight bytes, or a default one.          */
/*                                               */
/* Parameters: Pointer to an 8 char long array   */
/*             chars, or NULL for a default      */
/*             pattern.                          */
/*************************************************/

_kernel_oserror * dragbox_set_dotdash(char * eight)
{
  if (!eight) eight = "\360\360\360\360\360\360\360\360";

  /* Output char 23, then 6 (misc VDU; set dot-dash) */

  RetError(_swix(OS_WriteI + 23, 0));
  RetError(_swix(OS_WriteI + 6,  0));

  /* Now output the 8 bytes describing the pattern */

  return _swix(OS_WriteN,
               _INR(0,1),

               eight,
               8);
}

/*************************************************/
/* dragbox_cycle_pattern()                       */
/*                                               */
/* Cycle the dot-dash pattern for a 'rotating'   */
/* drag box.                                     */
/*************************************************/

void dragbox_cycle_pattern(void)
{
  int i;

  patternid --;

  if (patternid < 0) patternid = 7;

  /* Cycle the pattern */

  for (i = 0; i < 8; i++)
  {
    pattern1[i] = patterns1[patternid];
    pattern2[i] = patterns2[patternid];
  }

  return;
}

/*************************************************/
/* dragbox_plot_eor_box()                        */
/*                                               */
/* Plot a dotted rubber box using EOR. Should    */
/* only be used during a redraw loop.            */
/*                                               */
/* Parameters: A WimpRedrawWindowBlock pointer   */
/*             relevant to the redraw session;   */
/*                                               */
/*             Pointer to a BBox holding the     */
/*             min and max coords of the BBox    */
/*             (window work area coords, min     */
/*             values inclusive, max values      */
/*             exclusive).                       */
/*************************************************/

void dragbox_plot_eor_box(WimpRedrawWindowBlock * r, BBox * rect)
{
  BBox box = *rect;

  /* Convert the given rectangle work-area coords to screen coords */

  coords_box_toscreen(&box, r);

  /* Make xmax and ymax inclusive coords */

  box.xmax -= wimpt_dx();
  box.ymax -= wimpt_dy();

  /* Set the dash pattern */

  #ifdef TRACE
    if (tl & (1u<<27)) Printf("Set dotdash\n");
  #endif

  dragbox_set_dotdash(pattern);

  /* Set the colour and plot the box */

  #ifdef TRACE
    if (tl & (1u<<27)) Printf("Set colour\n");
  #endif

  _swix(Wimp_SetColour, _IN(0), 0x3f);

  #ifdef TRACE
    if (tl & (1u<<27)) Printf("Draw over %d, %d, %d, %d\n",box.xmin,box.ymin,box.xmax,box.ymax);
  #endif

  _swix(OS_Plot, _INR(0,2), 4,      box.xmin, box.ymin);
  _swix(OS_Plot, _INR(0,2), 5 | 24, box.xmax, box.ymin);
  _swix(OS_Plot, _INR(0,2), 5 | 48, box.xmax, box.ymax);
  _swix(OS_Plot, _INR(0,2), 5 | 48, box.xmin, box.ymax);
  _swix(OS_Plot, _INR(0,2), 5 | 48, box.xmin, box.ymin);

  return;
}

/*************************************************/
/* dragbox_update_eor_box()                      */
/*                                               */
/* Plot a dotted rubber box using EOR. Does its  */
/* own update redraw loop for the plot.          */
/*                                               */
/* Parameters: Window handle that the box is to  */
/*             lie within;                       */
/*                                               */
/*             Pointer to a BBox holding the     */
/*             min and max coords of the BBox    */
/*             (window work area coords, min     */
/*             values inclusive, max values      */
/*             exclusive).                       */
/*************************************************/

void dragbox_update_eor_box(int handle, BBox * rect)
{
  WimpGetWindowStateBlock s;
  WimpRedrawWindowBlock   r;
  int                     more = 0;

  s.window_handle = handle;
  if (wimp_get_window_state(&s)) return;

  /* Convert the given work area rectangle to screen coords */
  /* for redrawing                                          */

  r.window_handle = s.window_handle;
  r.visible_area  = *rect;
  r.xscroll       = s.xscroll;
  r.yscroll       = s.yscroll;

//  coords_box_toworkarea(&r.visible_area, (WimpRedrawWindowBlock *) &s);

  /* Start the update */

  wimp_update_window(&r, &more);

  /* Do the redraw */

  while (more)
  {
    #ifdef TRACE
      if (tl & (1u<<27)) Printf("Plot EOR\n");
    #endif

    dragbox_plot_eor_box(&r, rect);

    wimp_get_rectangle(&r, &more);
  }

  return;
}

/*************************************************/
/* dragbox_start_rotate_box()                    */
/*                                               */
/* Call before starting a 'rotate' drag box      */
/* plot.                                         */
/*************************************************/

void dragbox_start_rotate_box(void)
{
  pattern = pattern2;

  return;
}

/*************************************************/
/* dragbox_end_rotate_box()                      */
/*                                               */
/* Call after completing a 'rotate' drag box     */
/* plot.                                         */
/*************************************************/

void dragbox_end_rotate_box(void)
{
  pattern = pattern1;

  dragbox_cycle_pattern();

  return;
}



void dragbox_draw_box(void)
{
  #ifdef TRACE
    if (tl & (1u<<27)) Printf("Draw\n");
  #endif
}

void dragbox_remove_box(void)
{
  #ifdef TRACE
    if (tl & (1u<<27)) Printf("Remove\n");
  #endif
}

void dragbox_move_box(void)
{
  #ifdef TRACE
    if (tl & (1u<<27)) Printf("Move\n");
  #endif
}