#if !NO_SCCS_STRINGS
static char sccs_insert_c[] = "@(#)insert.c	128.1 1/20/93 19:39:03";
#endif /* NO_SCCS_STRINGS */
/****************************************************************************\

   (c) Copyright 1991 by Lotus Development Corporation
   All Rights Reserved

   Module:  insert.c

   Description:  Inserts one or more columns at the current cursor location.
   {INSERTCOLUMN} accepts a single optional input argument for the number of
   columns to insert.  (INSERTCOLUMN} copies the current column's formats
   and widths to the new columns. 

\****************************************************************************/

#define  LPI_MAIN_MODULE

#define  USE_REGISTER
#define  USE_CELL
#define  USE_RANGE
#define  USE_SHEET

#include "lpixport.h"

#define  INSERTCOLUMN_NAME  "insertcolumn"
#define  FIRST_ROW          1
#define  LAST_ROW           8192

/****************************************************************************\

The library function analogous to the 1-2-3 /WIC command requires a Sheet
object, column number, and number of columns as input.  The input argument
specifies the number of columns to insert.  We construct Sheet and Cell
objects based on the current cell pointer location and query the Cell for
for the current column.  After the insert call, we copy the contents of the
current column (source) to the new columns (target). Before we can perform
the copy, we need to construct source and target ranges.  The copy operation
copies both contents and formatting.  To remove the contents and preserve the
formatting, we subsequently erase the target range.  We also set the width
of all new columns to the width of the original column. If, at any stage in
the process, an error occurs, we destroy any objects we may have
created and return.

\****************************************************************************/

lushort insertcolumn (p_context, arg_count, LpiContext)
   LpiRegContextType   p_context;
   lushort             arg_count;
   lptr(CONTEXT)       LpiContext;
{
   lsshort        retval;
   lushort        apperr;
   lslong         theColumns;
   lushort        theArgType;
   lushort        theColumnNum, theSheetNum, theWidth;
   lmbcs          theFilename[LPI_CL_FILEPATH_BUFLEN];      
   LpiSheetType   theSheet;

   LpiRangeType   theSourceRange, theTargetRange;
   LpiCellType    theCell;

   /* determine number of columns to insert */

   retval = LpiRegGetArgType(0,&theArgType);
   switch (theArgType) {
      case LPI_T_ARG_TYPE_NUM:
         retval = LpiRegGetArgNumInt(0,&theColumns);
         if (retval != LPI_SUCCESS) return (LPI_SUCCESS);
         break;
      case LPI_T_ARG_TYPE_MSG:
         theColumns = 1L;
         break;
      default:
         return (LPI_SUCCESS);
         break;
   }

   /* construct an object for the current sheet */

   retval = LpiShConstructCurrent(&theSheet);
   if (retval != LPI_SUCCESS) return (LPI_SUCCESS);

   /* construct an object for the current cell */

   retval = LpiClConstructCurrent(&theCell);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      return (LPI_SUCCESS);
   }

   /* get current column */

   retval = LpiClGetColumn(theCell, &theColumnNum);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      return (LPI_SUCCESS);
   }

   /* insert columns */

   retval = LpiShInsert(theSheet, theColumnNum, (lushort)theColumns,
                        LPI_T_INSERT_COLUMNS, &apperr); 
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      return (LPI_SUCCESS);
   }
   theColumnNum += theColumns;

   /* construct source range after determining filename and sheet number */

   retval = LpiClGetWorkFileName(theCell, theFilename);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      return (LPI_SUCCESS);
   }

   retval = LpiClGetSheet(theCell, &theSheetNum);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      return (LPI_SUCCESS);
   }

   retval = LpiRngConstructCoords(&theSourceRange,
    LpiLptrToLmhdl(theFilename), (lulong)theSheetNum, (lulong)theColumnNum,
    FIRST_ROW, (lulong)theSheetNum, (lulong)theColumnNum, LAST_ROW, &apperr);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      return (LPI_SUCCESS);
   }

   /* construct target range */

   retval = LpiRngConstructCoords(&theTargetRange,
    LpiLptrToLmhdl(theFilename), (lulong)theSheetNum,
    (lulong)theColumnNum-theColumns, FIRST_ROW, (lulong)theSheetNum,
    (lulong)theColumnNum-1, LAST_ROW, &apperr);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      LpiRngDestroy(&theSourceRange);
      return (LPI_SUCCESS);
   }

   /* copy source to target to transfer formats */

   retval = LpiRngCopy(theSourceRange, theTargetRange, &apperr);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      LpiRngDestroy(&theSourceRange);
      LpiRngDestroy(&theTargetRange);
      return (LPI_SUCCESS);
   }

   /* erase the target range leaving formats intact */

   retval = LpiRngErase(theTargetRange, &apperr);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      LpiRngDestroy(&theSourceRange);
      LpiRngDestroy(&theTargetRange);
      return (LPI_SUCCESS);
   }

   /* get original column's width */

   retval = LpiClGetWidth(theCell, &theWidth);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      LpiRngDestroy(&theSourceRange);
      LpiRngDestroy(&theTargetRange);
      return (LPI_SUCCESS);
   }

   /* set width for new columns */

   retval = LpiRngSetWidth(theTargetRange, (lulong)theWidth);
   if (retval != LPI_SUCCESS) {
      LpiShDestroy(&theSheet);
      LpiClDestroy(&theCell);
      LpiRngDestroy(&theSourceRange);
      LpiRngDestroy(&theTargetRange);
      return (LPI_SUCCESS);
   }  

   /* destroy constructed objects */

   LpiShDestroy(&theSheet);
   LpiClDestroy(&theCell);
   LpiRngDestroy(&theSourceRange);
   LpiRngDestroy(&theTargetRange);
   return (LPI_SUCCESS);            
}

/************************************************************************\

   The following function, LpiBind, is called when 1-2-3 loads our add-in.
   In this function we load the Register module and register our @function.
   Use this function to perform any setup, such as allocating memory,
   opening files, etc.

\************************************************************************/

LpiBind(insert_b)
{
   lushort retval, arg_types[1];
   LpiRegContextType mycontext;

   /* Start loading pointers to used modules */

   LPI_SETUP_LOAD;

   if (LPI_LOAD_REGISTER != LPI_SUCCESS) LpiSignal (LPI_FAILURE);
   if (LPI_LOAD_CELL     != LPI_SUCCESS) LpiSignal (LPI_FAILURE);
   if (LPI_LOAD_RANGE    != LPI_SUCCESS) LpiSignal (LPI_FAILURE);
   if (LPI_LOAD_SHEET    != LPI_SUCCESS) LpiSignal (LPI_FAILURE);

   /*
      register an advanced macro keyword that accepts zero or more
      number arguments
   */ 

   arg_types[0] = LPI_T_ARG_TYPE_NUM;
   retval = LpiRegMacro(
            INSERTCOLUMN_NAME,
            insertcolumn,
            1,
            arg_types,
            &mycontext,
            LPI_T_REG_MAC_PASS_MSG);

   if (retval != LPI_SUCCESS) LpiSignal (LPI_FAILURE);

   LpiSignal (LPI_SUCCESS);
}

/************************************************************************\

   The following function, LpiUnbind, is called when 1-2-3 unloads our 
   add-in.  This function simply executes the macro LPI_UNBIND and signals
   no errors.  Use this function to perform any cleanup, such as deallocating
   memory you allocated in LpiBind, closing opened files, etc.

/************************************************************************/

LpiUnbind(insert_u)
{
   LPI_UNLOAD;                                    /* macro for cleanup */

   LpiSignal (LPI_SUCCESS);                       /* indicate no errors */
}
