/*-----------------------------------------------------------------------*\
| COMPONENT:                                                              |
|  Product:    Windows API for Magic  Ver 8.30                            |
|  Package:    MCF_API                                                    |
|  File:       GenertateTask.cpp : Create task for "list of values" and   |
|              call it from main program                                  |
| ABSTRACT:                                                               |
|  File contains example of API.	The code does following tasks				  |
|                                                                         |
|  1. Create Sub Task.                                                    |
|  2. Generate "select real" operations for each column.                  |
|  3. Generate "Form Controls"                                            |
|  4. Add "call task" operation in parent task.                           |
|                                                                         |
\*-----------------------------------------------------------------------*/

// Includes 
#include "demo.h"

// Defines
const float DIST_BTN_CONTROLS = 1.500f;  // Used in Table control generate.

// Variables 
PTTaskProperties	pTaskProp;			// contains task main table, task mode etc..
PTTaskInfo			pTaskInfo;			// holds subtask no, break levels
PTTaskOperation	pOperations;		// Flow table of break level
					
PTTaskSelect		pSelect;				// Select Operation reference

// Function prototypes

void GenerateOperations(int *columns, int col_nums,char update_var[2]);
void AddCallOperation(int prg, char AfterVar[2],int task_no);
void GenerateFormControls(int *columns, int col_nums);

void SetPushDefaults(PTFormControl pControl,int but_no);
void AttachPlacement( PTFormControl pControl);
void SetTableDefaults( PTFormControl pControl);
float SetEditCtrlProperties( PTFormControl pControl, PTColumn pColumns, BOOL label);


// Implementation of functions

void apg_lov(long prg_no, long tab_no, int *columns, int col_nums, char attachToCtrl[2])
{
	int currTask = 0;  // newly created task's "Task number".
	if(!(APIErrCode=OpenTask(prg_no)))
	{
		if(!(APIErrCode=GetTaskInformation(&pTaskInfo)))
		{
			currTask = pTaskInfo->subtasks +1 ;  // Last task
			if(!(APIErrCode = CreateTask()))
			{
				if(!(APIErrCode = OpenTask(currTask)))
				{
					if(!(APIErrCode = GetTaskProperties(&pTaskProp)))
					{
						PTTaskForm pTaskForms;

						// Update "Task Form's" Title
						APIErrCode=GetTaskForms( &pTaskForms);
						APIPutStr(&pTaskForms[1].name, pTableRepo[tab_no].name);
						pTaskForms[1].child_yn = 'N';
						APIErrCode=UpdateTaskForms( pTaskForms, 1);
						FreeTaskForms( pTaskForms, 1);

						// Set Main Table and task name of for task
						pTaskProp->main_table = tab_no;
						APIPutStr(&pTaskProp->name,"List Of Values");
						pTaskProp->mode = 'M';
						pTaskProp->select_table_ynexp = YES;
						if(!(APIErrCode = UpdateTaskProperties(pTaskProp)))
						{
							// Close/Open Task To store properties in application file
							CloseTask();
							APIErrCode=OpenTask(currTask);

							//  Generate operations for newly created task.
							GenerateOperations(columns,col_nums,attachToCtrl);

							//  Generate operations for newly created task.
							GenerateFormControls(columns,col_nums);
						}

						FreeTaskProperties(pTaskProp);
					}
					CloseTask();  // Child task
				} // End of CreateTask()
			}
			FreeTaskInformation(pTaskInfo);
		}
		CloseTask(); // Program Task
	}
	if(APIErrCode)
	{
		DisplayError(APIErrCode);
		return;
	}

	// Attach Sub Task To parent through task call operation
	AddCallOperation(prg_no,attachToCtrl,currTask);
	return ;
}


void GenerateOperations(int *columns, int col_nums, char update_var[2])
{
	PTTaskOperation pSuffixOp;  // Record Suffix Operation Table
	PTTaskUpdate    pUpdate;    // Update operation reference.

	// First Create Real Variables for sub task
	pOperations = (PTTaskOperation)APIMalloc( sizeof(TTaskOperation)*(col_nums+1));

	for(int oper_no = 1; oper_no <= col_nums ; oper_no++)
	{
		pOperations[oper_no].operation_type = SELECT_OP; 
		pSelect =(PTTaskSelect) &pOperations[oper_no].operation_details;
		pSelect->mode = 'R' ;
		pSelect->column = columns[oper_no];
		pSelect->flow_mode = 'S';
		pSelect->flow_direction = 'C';
		pSelect->flow_condition_ynexp = YES ;
	}

	if(APIErrCode=UpdateTaskOperations(1, MAIN , pOperations , col_nums))
		DisplayError(APIErrCode);
	APIFree( pOperations);

	// Store operations in global variable
	// Memory Allocated here is released in GenerateFormControls()
	GetTaskOperations(1,MAIN,&pOperations);

	pSuffixOp = (PTTaskOperation)APIMalloc( sizeof(TTaskOperation) * 2);

	//
	// ADD : Update command in record suffix of a task.
	//

	// First Create one expression to update parent task's "form control"
	PTTaskExpression pExpr = (PTTaskExpression)APIMalloc( sizeof(TTaskExpression) * 2);
	
	//	
	// We suppose controls data's type and column's type is same,
	// if not, it's users responsiblity of converting to proper type.
	//
	pSelect = (PTTaskSelect)&pOperations[return_column_num].operation_details;
	pExpr[1].expression = (char *)APIMalloc(3);
	strncpy(pExpr[1].expression,pSelect->variable_name,2);
	
	if(APIErrCode = UpdateTaskExpressions( pExpr,1))
		DisplayError(APIErrCode);
	FreeTaskExpressions( pExpr,1);

	
	// Now Add one update operation in record suffix of sub task.
	pSuffixOp[1].operation_type = UPDATE_OP; 
	pUpdate =(PTTaskUpdate) &pSuffixOp[1].operation_details;
	memcpy(&pUpdate->variable_name,update_var,2);
	pUpdate->expression = 1;
	pUpdate->how_mode = 'N';
	pUpdate->undo_yn = 'Y';
	pUpdate->flow_mode = 'S';
	pUpdate->flow_direction = 'C';
	pUpdate->flow_condition_ynexp = YES ;

	if(APIErrCode=UpdateTaskOperations(1, SUFFIX , pSuffixOp , 1))
		DisplayError(APIErrCode);

	APIFree(pSuffixOp);

}

void GenerateFormControls(int *columns, int col_nums)
{
	float table_width;
	PTColumn pColumns;
	PTFormControl pControls;	

	int ctrlsToGenerate = 
							col_nums *  // Table control Columns
							2			+	// Static Column Controls
							1			+  // Table Control
							2			;  // Push Buttons. */

	pControls = (PTFormControl)APIMalloc(sizeof(TFormControl) *(ctrlsToGenerate+1));

	if(APIErrCode = OpenTable(pTaskProp->main_table))
		DisplayError(APIErrCode);
	else
	{
		if(APIErrCode=GetTableColumns(&pColumns))
		{
			DisplayError(APIErrCode);
			return;
		}
		CloseTable();
	}

	// Set Table
	pControls[1].columns = col_nums;
	pControls[1].number_of_columns = col_nums;
	pControls[1].column_width = (float*)APIMalloc( sizeof(float)* (col_nums +1));
	SetTableDefaults( &pControls[1]);

	// Set Columns
	for (int col = 1;col <= col_nums ; col++)
	{
		pControls[col*2  ].type = VISUAL_TYPE_STATIC;
		SetEditCtrlProperties(&pControls[col*2 ],&pColumns[columns[col]],TRUE);

		pControls[col*2+1].type = VISUAL_TYPE_EDIT;

		pSelect = (PTTaskSelect)&pOperations[col].operation_details;
		memcpy(pControls[col*2+1].data,pSelect->variable_name,2);

		table_width = SetEditCtrlProperties(&pControls[col*2+1],&pColumns[columns[col]],FALSE);
		// Set Dividers column width of table control
		pControls[1].column_width[col] = pControls[col*2+1].width + DIST_BTN_CONTROLS ;

	}
	
	FreeTableColumns(pColumns,pTableRepo[pTaskProp->main_table].columns);
	
	// Set Forms "Table control's" width
	pControls[1].width = 
					table_width +	// All Columns Width 
					1.250f ;			// scroll bar length

	// Set Push Buttons
	pControls[col*2  ].type = VISUAL_TYPE_PUSH;
	SetPushDefaults(&pControls[col*2  ],1); // OK

	pControls[col*2+1].type = VISUAL_TYPE_PUSH;
	SetPushDefaults(&pControls[col*2+1],2); // Cancel

	// Update Form Controls 
	if(APIErrCode = UpdateFormControls( 1, pControls , ctrlsToGenerate))
		DisplayError(APIErrCode);
	
	// Fix - QCR # 926932
	PTTaskForm pTaskForms;
   GetTaskForms (&pTaskForms);
   FreeFormControls (pTaskForms[1].interface_type, pControls,ctrlsToGenerate);
   FreeTaskForms (pTaskForms, pTaskInfo->forms);

	// Allocated in Generate Operations Free it now.
	FreeTaskOperations(pOperations,col_nums);

}

void AttachPlacement( PTFormControl pControl)
{
	PTPlacement place = (PTPlacement)APIMalloc( sizeof( TPlacement));
	pControl->placement = place;
}


void SetTableDefaults( PTFormControl pControl)
{
	pControl->type = VISUAL_TYPE_TABLE;
	pControl->style = '3';
	pControl->border_style = 'T';
	pControl->line_divider_yn = 'Y';
	pControl->title_height = 1.375;
	pControl->row_height = 1.500;
	pControl->left = 1.0;
	pControl->top = 1.0;
	pControl->height = 18.0;
	pControl->color = 5;
	pControl->fix_size_table_yn = 'N';
	pControl->title_on_every_page_yn = 'N';
	pControl->enable_rich_text_yn = 'N' ;
	pControl->scroll_bar_yn = 'Y';
	AttachPlacement(pControl);
}


float SetEditCtrlProperties( PTFormControl pControl, PTColumn pColumns, BOOL label)
{
	static float xpos = 1.750 ;
	pControl->left = xpos;
	// Calculate controls width
	pControl->width = pColumns->size + 2.500f;

	if( label ) // Static control
	{
		pControl->top = 1.250;
		pControl->height = 1.000;
		APIPutStr(&pControl->label, pColumns->name);
		pControl->enable_rich_text_yn = 'N';
		memset(&pControl->static_type,'N', 8);
		pControl->border_style = 'N';
		pControl->font = 2;
	}
	else			// Edit contols property
	{
		xpos += pControl->width + DIST_BTN_CONTROLS ;

		pControl->top = 2.625;
		pControl->height = 1.000;

		APIPutStr(&pControl->format, pColumns->picture);
		pControl->attribute = pColumns->attr;
		pControl->must_input_ynexp = NO;
		pControl->modifiable_ynexp = NO;
		pControl->vertical_scroll_yn = 'N';
		pControl->horizontal_scroll_yn = 'N';
		pControl->password_edit_yn = 'N';
		APIPutStr(&pControl->viewed_currency, "EURO");
		pControl->border_style = 'N';
		pControl->font = 1;

	}

	// Common Properties of static and edit control
	pControl->style = '2';
	APIPutStr(&pControl->control_name,pColumns->name);
	APIPutStr(&pControl->text,pColumns->name);
	pControl->help_ynexp = YES;
	pControl->tooltip_exp = YES;
	pControl->multiline_edit_yn = 'N';

	pControl->line_3d_yn = 'N';
	pControl->line_style = 'R';

	pControl->father_number = 1;
	pControl->color = 1;
	pControl->vertical_alignment = 'C';
	pControl->horizontal_alignment = 'R';
	AttachPlacement(pControl);

	return xpos; // Used to calulate table width and divider's width.
}

void SetPushDefaults(PTFormControl pControl,int but_no)
{
	pControl->data[0] = '?';
	pControl->data[1] = '?';
	pControl->top = 20.0;
	pControl->width = 12.0;
	pControl->height = 1.750;
	pControl->font = 1;
	pControl->color = 1;
	APIPutStr(&pControl->image_file,"");

	if(but_no == 1) // Select Button
	{
		APIPutStr( &pControl->label, "Select");
		pControl->left = 2.000f;
		APIPutStr(&pControl->push_button_action,"Select");
		APIPutStr(&pControl->control_name,"Select");
	}
	else
	{
		APIPutStr( &pControl->label, "Cancel");
		pControl->left = 15.0;
		APIPutStr(&pControl->push_button_action,"Exit");
		APIPutStr(&pControl->control_name,"Cancel");
	}
	AttachPlacement(pControl);
}


// Add Operation in main task from where lov is called.
void AddCallOperation(int prg, char AfterVar[2],int task_no)
{
	PTTaskOperation	pAddOperations,   // holds New Operations of record main
							pOldOperations;   // Temporary store operation table 
	PTTaskInfo			pTaskInfo;			// For break levels count
	PTTaskBreakLevel	pBreakLevels;     // For operation count of record main
	int					oper_no;				// Current operation num
	

	// Open Task for processing
	OpenTask(prg);

	GetTaskInformation(&pTaskInfo);
	GetTaskBreakLevels(&pBreakLevels);
	GetTaskOperations(1, MAIN, &pAddOperations);

	// Find location to add call operation in record main flow table.
	for( oper_no = 1; oper_no < pBreakLevels[1].main_operations_num; oper_no++)
	{
		if( pAddOperations[oper_no].operation_type = SELECT_OP)
		{
			pSelect = (PTTaskSelect)(&pAddOperations[oper_no].operation_details);
			if (strncmp(AfterVar, pSelect->variable_name,2) == 0)
				break;  // when we got operation.
		}
	}

	pOldOperations = pAddOperations;
	
	// Copy Existing operations 
	pAddOperations =(PTTaskOperation) APIMalloc( sizeof(TTaskOperation) *
		(pBreakLevels[1].main_operations_num+2));
	memcpy( pAddOperations,pOldOperations,(oper_no+1)*sizeof(TTaskOperation));
	memcpy( &pAddOperations[oper_no+2],&pOldOperations[oper_no+1],
		(pBreakLevels[1].main_operations_num-oper_no)*sizeof(TTaskOperation));
	
	// Set Fields for call operation
	pAddOperations[oper_no+1].isn = 0;
	pAddOperations[oper_no+1].operation_type = CALL_OP;
	PTTaskCall pCallOperation = (PTTaskCall)pAddOperations[oper_no+1].operation_details;
	pCallOperation->mode = 'T';
	pCallOperation->num = task_no;
	pCallOperation->flow_mode = 'A';
	pCallOperation->flow_direction = 'C';
	pCallOperation->flow_condition_ynexp = YES ;

	// Update Record main's operation table 
	if(APIErrCode = UpdateTaskOperations(1, MAIN, pAddOperations,pBreakLevels[1].main_operations_num+1))
		DisplayError(APIErrCode);
	FreeTaskOperations( pOldOperations,pBreakLevels[1].main_operations_num);
	APIFree(pAddOperations);

	FreeTaskBreakLevels(pBreakLevels);
	FreeTaskInformation(pTaskInfo);

	CloseTask();
}

