This is ImprovConnector.m in view mode; [Download] [Up]
// ImprovConnector.m
// By Judy D. Halchin, Educational Computing Services, Allegheny College.
// Copyright 1993 Allegheny College.
// You may freely copy, distribute and reuse this code.
// Allegheny College and the author disclaim any warranty of any kind,
// expressed or implied, as to its fitness for any particular use.
// This work was partially supported by a Teacher Preparation grant from the
// National Science Foundation.
#import "ImprovConnector.h"
#import "imxPublicAPI.h"
@implementation ImprovConnector
enum errorMessages
{
IC_GETSELECTION = NX_APPBASE,
IC_GETINFO,
IC_GETCELLVALUE,
IC_SELECTIONTYPE,
IC_GETRANGE,
IC_SETSELECTION,
IC_ADDITEMS,
IC_RENAME,
IC_SETCELLVALUE,
IC_UPDATE,
IC_NUMBERCOLUMNS,
IC_NEWSHEET,
IC_BADPARAMETERS,
IC_GETROWS,
IC_GETCOLUMNS,
IC_GETCATEGORIES,
IC_NUMBERCATEGORIES,
IC_BADCATEGORIES,
IC_GETITEMINFO,
IC_GETRANGEINFO,
IC_COLUMNCHECK,
IC_CELLTYPE,
IC_ADDCOLUMNS
};
enum handlingValues
{
IC_USEVALUE = 0,
IC_USEZERO,
IC_SKIPVALUE,
IC_CONVERT,
IC_ERROR
};
- init
{
[super init];
NXWriteDefault("Improv", "enableOakumPort", "Yes");
sheet = (char *)malloc(1);
model = (char *)malloc(1);
strcpy(sheet, "");
strcpy(model, "");
emptyCellHandling = WB_ZERO;
textCellHandling = WB_ERROR;
return self;
}
- setCellHandlingForEmpty:(int)handlingForEmpty text:(int)handlingForText
{
emptyCellHandling = handlingForEmpty;
textCellHandling = handlingForText;
return self;
}
- (int)doubleData:(double **)data fromColumn:(char *)columnName
dataCount:(int *)numRows
{
return [self dataType:WB_DOUBLEDATA double:data float:NULL int:NULL
string:NULL fromColumn:columnName dataCount:numRows];
}
- (int)floatData:(float **)data fromColumn:(char *)columnName
dataCount:(int *)numRows
{
return [self dataType:WB_FLOATDATA double:NULL float:data int:NULL
string:NULL fromColumn:columnName dataCount:numRows];
}
- (int)intData:(int **)data fromColumn:(char *)columnName
dataCount:(int *)numRows
{
return [self dataType:WB_INTDATA double:NULL float:NULL int:data
string:NULL fromColumn:columnName dataCount:numRows];
}
- (int)stringData:(char ***)data fromColumn:(char *)columnName
dataCount:(int *)numRows
{
return [self dataType:WB_STRINGDATA double:NULL float:NULL int:NULL
string:data fromColumn:columnName dataCount:numRows];
}
- (int)dataType:(int)dataType double:(double **)doubleData
float:(float **)floatData int:(int **)intData
string:(char ***)stringData fromColumn:(char *)columnName
dataCount:(int *)numRows
{
char *selName, *viewName, *sheetName, *modelName, *lastRow, *firstRow;
char *parent, **rowNames, cellName[100], *cellString, *parentName;
char **categoryNames, *categoryList;
imxSelType selType;
imxCellType cellType;
int imxReturnCode, myReturnCode=0, rowCount, rowIndex, categoryCount;
int dataIndex;
double cellValue;
BOOL found;
NX_DURING
// make sure the named column really exists and get its category
// get the current sheet and model
if ((imxReturnCode = imxGetSelection(&selName, &selType, &viewName,
&sheetName, &modelName)) != 0)
NX_RAISE(IC_GETSELECTION, &imxReturnCode, NULL);
sheet = (char *)realloc(sheet, strlen(sheetName)+1);
model = (char *)realloc(model, strlen(modelName)+1);
strcpy(sheet, sheetName);
strcpy(model, modelName);
// make sure we can find the given column and that it is a column
if ((imxReturnCode = imxGetItemInfo(&parentName, &firstRow,
&lastRow, columnName, sheet, model)) != 0)
NX_RAISE(IC_GETINFO, &imxReturnCode, NULL);
if (parentName == NULL)
NX_RAISE(IC_COLUMNCHECK, &imxReturnCode, NULL);
parent = (char *)malloc(strlen(parentName) + 1);
strcpy(parent, parentName);
if ((imxReturnCode = imxGetCategoryList(&categoryList, sheet,
model)) != 0)
NX_RAISE(IC_GETCATEGORIES, &imxReturnCode, NULL);
[self getNames:&categoryNames fromList:categoryList
count:&categoryCount];
for (rowIndex = 0, found = NO; (rowIndex < categoryCount)
&& !found; rowIndex++)
if (strcmp(categoryNames[rowIndex], parent) == 0)
found = YES;
[self freeData:categoryNames count:categoryCount];
if (!found)
{
free(parent);
NX_RAISE(IC_COLUMNCHECK, NULL, NULL);
}
// get the list of row names
if ((myReturnCode = [self getRows:&rowNames rowCount:&rowCount
forColumnCategory:parent]) != 0)
NX_RAISE(IC_GETROWS, NULL, NULL);
free(parent);
// get the data from the column
switch (dataType)
{
case WB_DOUBLEDATA:
*doubleData = (double *)malloc(rowCount * sizeof(double));
break;
case WB_FLOATDATA:
*floatData = (float *)malloc(rowCount * sizeof(float));
break;
case WB_INTDATA:
*intData = (int *)malloc(rowCount * sizeof(int));
break;
case WB_STRINGDATA:
*stringData = (char **)malloc(rowCount * sizeof(char *));
break;
}
for (rowIndex = 0, dataIndex = 0; rowIndex < rowCount; rowIndex++)
{
sprintf(cellName, "%s:%s", columnName, rowNames[rowIndex]);
if ((imxReturnCode = imxGetCellValue(cellName, &cellType,
&cellValue, &cellString, sheet, model)) != 0)
NX_RAISE(IC_GETCELLVALUE, &imxReturnCode, &dataType);
switch ([self handleCell:cellType forData:dataType])
{
case IC_SKIPVALUE:
dataIndex--;
break;
case IC_USEVALUE:
switch (dataType)
{
case WB_DOUBLEDATA:
(*doubleData)[dataIndex] = cellValue;
break;
case WB_FLOATDATA:
(*floatData)[dataIndex] = cellValue;
break;
case WB_INTDATA:
(*intData)[dataIndex] = cellValue;
break;
case WB_STRINGDATA:
(*stringData)[dataIndex] = (char *)malloc
(strlen(cellString) + 1);
strcpy((*stringData)[dataIndex], cellString);
break;
}
break;
case IC_USEZERO:
switch (dataType)
{
case WB_DOUBLEDATA:
(*doubleData)[dataIndex] = 0;
break;
case WB_FLOATDATA:
(*floatData)[dataIndex] = 0;
break;
case WB_INTDATA:
(*intData)[dataIndex] = 0;
break;
case WB_STRINGDATA:
(*stringData)[dataIndex] = (char *)malloc(1);
strcpy((*stringData)[dataIndex], "");
break;
}
break;
case IC_CONVERT: // data type must be string to get this case
(*stringData)[dataIndex] = (char *)malloc(15);
sprintf((*stringData)[dataIndex], "%f", cellValue);
[self deleteTrailingZeros:(*stringData)[dataIndex]];
break;
case IC_ERROR:
NX_RAISE(IC_CELLTYPE, NULL, NULL);
break;
}
dataIndex++;
}
// send back the number of rows
*numRows = dataIndex;
// free stuff
[self freeData:rowNames count:rowCount];
NX_HANDLER
switch (NXLocalHandler.code)
{
case IC_GETSELECTION:
if (*(int *)NXLocalHandler.data1 == imxerr_NO_SELECTION)
myReturnCode = WB_NOTHINGSELECTED;
else
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_GETINFO:
if (*(int *)NXLocalHandler.data1 == imxerr_ITEM_NOT_FOUND)
myReturnCode = WB_NOSUCHCOLUMN;
else
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_GETCATEGORIES:
free(parent);
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_GETROWS:
free(parent);
break;
case IC_COLUMNCHECK:
myReturnCode = WB_NOSUCHCOLUMN;
break;
case IC_GETCELLVALUE:
switch (dataType)
{
case WB_DOUBLEDATA:
free(*doubleData);
break;
case WB_FLOATDATA:
free(*floatData);
break;
case WB_INTDATA:
free(*intData);
break;
case WB_STRINGDATA:
[self freeData:*stringData count:dataIndex];
break;
}
[self freeData:rowNames count:rowCount];
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_CELLTYPE:
switch (dataType)
{
case WB_DOUBLEDATA:
free(*doubleData);
break;
case WB_FLOATDATA:
free(*floatData);
break;
case WB_INTDATA:
free(*intData);
break;
case WB_STRINGDATA:
[self freeData:*stringData count:dataIndex];
break;
}
[self freeData:rowNames count:rowCount];
myReturnCode = WB_WRONGCELLTYPE;
break;
default:
NX_RERAISE();
}
NX_ENDHANDLER
return myReturnCode;
}
- (int)doubleData:(double ***)data fromSelectedColumnsCount:(int *)numColumns
byRows:(BOOL)byRows dataCount:(int *)numRows
{
return [self dataType:WB_DOUBLEDATA double:data float:NULL int:NULL
string:NULL fromSelectedColumnsCount:numColumns
byRows:byRows dataCount:numRows];
}
- (int)floatData:(float ***)data fromSelectedColumnsCount:(int *)numColumns
byRows:(BOOL)byRows dataCount:(int *)numRows
{
return [self dataType:WB_FLOATDATA double:NULL float:data int:NULL
string:NULL fromSelectedColumnsCount:numColumns
byRows:byRows dataCount:numRows];
}
- (int)intData:(int ***)data fromSelectedColumnsCount:(int *)numColumns
byRows:(BOOL)byRows dataCount:(int *)numRows
{
return [self dataType:WB_INTDATA double:NULL float:NULL int:data
string:NULL fromSelectedColumnsCount:numColumns
byRows:byRows dataCount:numRows];
}
- (int)stringData:(char ****)data fromSelectedColumnsCount:(int *)numColumns
byRows:(BOOL)byRows dataCount:(int *)numRows
{
return [self dataType:WB_STRINGDATA double:NULL float:NULL int:NULL
string:data fromSelectedColumnsCount:numColumns
byRows:byRows dataCount:numRows];
}
- (int)dataType:(int)dataType double:(double ***)doubleData
float:(float ***)floatData
int:(int ***)intData
string:(char ****)stringData
fromSelectedColumnsCount:(int *)numColumns
byRows:(BOOL)byRows dataCount:(int *)numRows
{
char *selectionName, *viewName, *sheetName, *modelName, cellName[100];
char *parent, *selection, *cellString;
int itemCount, itemIndex, rowCount, rowIndex;
int firstIndex, secondIndex, firstCount, secondCount;
int imxReturnCode, myReturnCode = 0, dataIndex;
imxSelType selectionType;
imxCellType cellType;
char *itemList, *selectedCategory, **itemNames, **rowNames;
double cellValue;
NX_DURING
// find out what sort of thing is currently selected, should be item(s)
if ((imxReturnCode = imxGetSelection(&selectionName, &selectionType,
&viewName, &sheetName, &modelName)) != 0)
NX_RAISE(IC_GETSELECTION, &imxReturnCode, NULL);
if (selectionType != imxsel_ITEM)
NX_RAISE(IC_SELECTIONTYPE, NULL, NULL);
selection = (char *)malloc(strlen(selectionName) + 1);
strcpy(selection, selectionName);
strcpy(sheet, "");
strcpy(model, "");
// separate names of selected items and count them
if ((imxReturnCode = imxGetItemRangeInfo(&parent, &itemList, selection,
sheet, model)) != 0)
NX_RAISE(IC_GETRANGE, &imxReturnCode, NULL);
free(selection);
selectedCategory = (char *)malloc(strlen(parent) + 1);
strcpy(selectedCategory, parent);
[self getNames:&itemNames fromList:itemList count:&itemCount];
// get the list of row names
if ((myReturnCode = [self getRows:&rowNames rowCount:&rowCount
forColumnCategory:selectedCategory]) != 0)
NX_RAISE(IC_GETROWS, NULL, NULL);
free(selectedCategory);
// get the data from the cells and store it in an array
if (byRows)
{
firstCount = rowCount;
secondCount = itemCount;
}
else
{
firstCount = itemCount;
secondCount = rowCount;
}
switch (dataType)
{
case WB_DOUBLEDATA:
*doubleData = (double **)malloc(firstCount * sizeof(double *));
break;
case WB_FLOATDATA:
*floatData = (float **)malloc(firstCount * sizeof(float *));
break;
case WB_INTDATA:
*intData = (int **)malloc(firstCount * sizeof(int *));
break;
case WB_STRINGDATA:
*stringData = (char ***)malloc(firstCount * sizeof(char **));
break;
}
for (firstIndex = 0,dataIndex=0; firstIndex < firstCount; firstIndex++)
{
switch (dataType)
{
case WB_DOUBLEDATA:
(*doubleData)[dataIndex] = (double *)malloc
(secondCount * sizeof(double));
break;
case WB_FLOATDATA:
(*floatData)[dataIndex] = (float *)malloc
(secondCount * sizeof(float));
break;
case WB_INTDATA:
(*intData)[dataIndex] = (int *)malloc
(secondCount * sizeof(int));
break;
case WB_STRINGDATA:
(*stringData)[dataIndex] = (char **)malloc
(secondCount * sizeof(char *));
break;
}
for (secondIndex = 0; secondIndex < secondCount; secondIndex++)
{
if (byRows)
{
rowIndex = firstIndex;
itemIndex = secondIndex;
}
else
{
rowIndex = secondIndex;
itemIndex = firstIndex;
}
sprintf(cellName, "%s:%s", itemNames[itemIndex],
rowNames[rowIndex]);
if ((imxReturnCode = imxGetCellValue(cellName, &cellType,
&cellValue, &cellString, sheet, model)) != 0)
NX_RAISE(IC_GETCELLVALUE, NULL, NULL);
switch ([self handleCell:cellType forData:dataType])
{
case IC_SKIPVALUE:
dataIndex--;
secondIndex = secondCount;
break;
case IC_USEVALUE:
switch (dataType)
{
case WB_DOUBLEDATA:
(*doubleData)[dataIndex][secondIndex]
= cellValue;
break;
case WB_FLOATDATA:
(*floatData)[dataIndex][secondIndex]
= cellValue;
break;
case WB_INTDATA:
(*intData)[dataIndex][secondIndex] = cellValue;
break;
case WB_STRINGDATA:
(*stringData)[dataIndex][secondIndex]
= (char *)malloc(strlen(cellString) + 1);
strcpy((*stringData)[dataIndex][secondIndex],
cellString);
break;
}
break;
case IC_USEZERO:
switch (dataType)
{
case WB_DOUBLEDATA:
(*doubleData)[dataIndex][secondIndex] = 0;
break;
case WB_FLOATDATA:
(*floatData)[dataIndex][secondIndex] = 0;
break;
case WB_INTDATA:
(*intData)[dataIndex][secondIndex] = 0;
break;
case WB_STRINGDATA:
(*stringData)[dataIndex][secondIndex]
= (char *)malloc(1);
strcpy((*stringData)[dataIndex][secondIndex],
"");
break;
}
break;
case IC_CONVERT: // data type must be string to get this
(*stringData)[dataIndex][secondIndex]
= (char *)malloc(15);
sprintf((*stringData)[dataIndex][secondIndex], "%f",
cellValue);
[self deleteTrailingZeros:
(*stringData)[dataIndex][secondIndex]];
break;
case IC_ERROR:
NX_RAISE(IC_CELLTYPE, NULL, NULL);
break;
}
}
dataIndex++;
}
// send back the number of rows and columns
if (byRows)
{
*numColumns = itemCount;
*numRows = dataIndex;
}
else
{
*numColumns = dataIndex;
*numRows = rowCount;
}
// free stuff
[self freeData:itemNames count:itemCount];
[self freeData:rowNames count:rowCount];
NX_HANDLER
switch (NXLocalHandler.code)
{
case IC_GETSELECTION:
if (*(int *)NXLocalHandler.data1 == imxerr_NO_SELECTION)
myReturnCode = WB_NOTHINGSELECTED;
else
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_SELECTIONTYPE:
myReturnCode = WB_WRONGTYPEOFSELECTION;
break;
case IC_GETRANGE:
free(selection);
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_GETROWS:
[self freeData:itemNames count:itemCount];
[self freeData:rowNames count:rowCount];
break;
case IC_GETCELLVALUE:
[self freeData:itemNames count:itemCount];
[self freeData:rowNames count:rowCount];
switch (dataType)
{
case WB_DOUBLEDATA:
[self freeData:*doubleData count:dataIndex];
break;
case WB_FLOATDATA:
[self freeData:*floatData count:dataIndex];
break;
case WB_INTDATA:
[self freeData:*intData count:dataIndex];
break;
case WB_STRINGDATA:
[self freeStringData:*stringData
counts:dataIndex-1 :secondCount];
if (secondIndex > 0)
[self freeData:(*stringData)[dataIndex]
count:secondIndex];
break;
}
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_CELLTYPE:
[self freeData:itemNames count:itemCount];
[self freeData:rowNames count:rowCount];
switch (dataType)
{
case WB_DOUBLEDATA:
[self freeData:*doubleData count:dataIndex];
break;
case WB_FLOATDATA:
[self freeData:*floatData count:dataIndex];
break;
case WB_INTDATA:
[self freeData:*intData count:dataIndex];
break;
case WB_STRINGDATA:
[self freeStringData:*stringData
counts:dataIndex-1 :secondCount];
if (secondIndex > 0)
[self freeData:(*stringData)[dataIndex]
count:secondIndex];
break;
}
myReturnCode = WB_WRONGCELLTYPE;
break;
default:
NX_RERAISE();
}
NX_ENDHANDLER
return myReturnCode;
}
- (int)fillColumnsCount:(int)numColumns startingAt:(char *)columnName
withDoubleData:(double **)data
byRows:(BOOL)byRows dataCount:(int)numRows
{
return [self fillColumnsCount:numColumns startingAt:columnName
withDataType:WB_DOUBLEDATA double:data
float:NULL int:NULL string:NULL
byRows:byRows dataCount:numRows];
}
- (int)fillColumnsCount:(int)numColumns startingAt:(char *)columnName
withFloatData:(float **)data
byRows:(BOOL)byRows dataCount:(int)numRows
{
return [self fillColumnsCount:numColumns startingAt:columnName
withDataType:WB_FLOATDATA double:NULL
float:data int:NULL string:NULL
byRows:byRows dataCount:numRows];
}
- (int)fillColumnsCount:(int)numColumns startingAt:(char *)columnName
withIntData:(int **)data
byRows:(BOOL)byRows dataCount:(int)numRows
{
return [self fillColumnsCount:numColumns startingAt:columnName
withDataType:WB_INTDATA double:NULL
float:NULL int:data string:NULL
byRows:byRows dataCount:numRows];
}
- (int)fillColumnsCount:(int)numColumns startingAt:(char *)columnName
withStringData:(char ***)data
byRows:(BOOL)byRows dataCount:(int)numRows
{
return [self fillColumnsCount:numColumns startingAt:columnName
withDataType:WB_STRINGDATA double:NULL
float:NULL int:NULL string:data
byRows:byRows dataCount:numRows];
}
- (int)fillColumnsCount:(int)numColumns startingAt:(char *)columnName
withDataType:(int)dataType double:(double **)doubleData
float:(float **)floatData int:(int **)intData
string:(char ***)stringData
byRows:(BOOL)byRows dataCount:(int)numRows
{
char *selName, *viewName, *sheetName, *modelName, *lastRow, *firstRow;
char *parent, **rowNames, cellName[500], *parentName, *categoryList;
char **categoryNames, *cellString, *rowCategory, **columnNames;
char **fillColumnNames;
imxSelType selType;
imxCellType cellType;
int imxReturnCode, myReturnCode = 0, rowCount, rowIndex, categoryCount;
int colIndex, colCount;
BOOL found;
double cellValue;
NX_DURING
// make sure the starting column really exists and get its category
// get the current sheet and model
if ((imxReturnCode = imxGetSelection(&selName, &selType, &viewName,
&sheetName, &modelName)) != 0)
NX_RAISE(IC_GETSELECTION, &imxReturnCode, NULL);
sheet = (char *)realloc(sheet, strlen(sheetName)+1);
model = (char *)realloc(model, strlen(modelName)+1);
strcpy(sheet, sheetName);
strcpy(model, modelName);
// make sure we can find the given column and that it is a column
if ((imxReturnCode = imxGetItemInfo(&parentName, &firstRow,
&lastRow, columnName, sheet, model)) != 0)
NX_RAISE(IC_GETINFO, &imxReturnCode, NULL);
if (parentName == NULL)
NX_RAISE(IC_COLUMNCHECK, &imxReturnCode, NULL);
parent = (char *)malloc(strlen(parentName) + 1);
strcpy(parent, parentName);
if ((imxReturnCode = imxGetCategoryList(&categoryList, sheet,
model)) != 0)
NX_RAISE(IC_GETCATEGORIES, &imxReturnCode, NULL);
[self getNames:&categoryNames fromList:categoryList
count:&categoryCount];
for (rowIndex = 0, found = NO; rowIndex < categoryCount;
rowIndex++)
if (strcmp(categoryNames[rowIndex], parent) == 0)
found = YES;
else
{
rowCategory = (char *)malloc
(strlen(categoryNames[rowIndex]) + 1);
strcpy(rowCategory, categoryNames[rowIndex]);
}
[self freeData:categoryNames count:categoryCount];
if (!found)
{
free(parent);
NX_RAISE(IC_COLUMNCHECK, NULL, NULL);
}
// get the list of rows for the given column
if ((myReturnCode = [self getRows:&rowNames rowCount:&rowCount
forColumnCategory:parent]) != 0)
NX_RAISE(IC_GETROWS, NULL, NULL);
// if there aren't enough rows for the data, add some at the end
if (rowCount < numRows)
if ((myReturnCode = [self addColumns:NULL count:numRows-rowCount
afterColumn:rowNames[rowCount-1]]) != 0)
NX_RAISE(IC_ADDCOLUMNS, NULL, NULL);
[self freeData:rowNames count:rowCount];
if ((myReturnCode = [self getRows:&rowNames rowCount:&rowCount
forColumnCategory:parent]) != 0)
NX_RAISE(IC_GETROWS, NULL, NULL);
// get the list of column names, make sure there are enough
if ((myReturnCode = [self getRows:&columnNames rowCount:&colCount
forColumnCategory:rowCategory]) != 0)
NX_RAISE(IC_GETCOLUMNS, NULL, NULL);
for (colIndex = 0, found = NO; (colIndex < colCount) && !found;
colIndex++)
if (strcmp(columnNames[colIndex], columnName) == 0)
{
fillColumnNames = columnNames + colIndex;
found = YES;
}
free(parent);
if (colCount - colIndex + 1 < numColumns)
NX_RAISE(IC_NUMBERCOLUMNS, NULL, NULL);
// insert the data into the columns
if (dataType == WB_STRINGDATA)
{
cellType = cval_TEXT;
cellValue = 0;
}
else
{
cellType = cval_NUMBER;
cellString = (char *)malloc(1);
strcpy(cellString, "");
}
for (rowIndex = 0; rowIndex < numRows; rowIndex++)
for (colIndex = 0; colIndex < numColumns; colIndex++)
{
switch (dataType)
{
case WB_DOUBLEDATA:
cellValue = doubleData[rowIndex][colIndex];
break;
case WB_FLOATDATA:
cellValue = floatData[rowIndex][colIndex];
break;
case WB_INTDATA:
cellValue = intData[rowIndex][colIndex];
break;
case WB_STRINGDATA:
cellString = (char *)malloc
(strlen(stringData[rowIndex][colIndex]) + 1);
strcpy(cellString, stringData[rowIndex][colIndex]);
break;
}
sprintf(cellName, "%s:%s", fillColumnNames[colIndex],
rowNames[rowIndex]);
if ((imxReturnCode = imxSetCellValue(cellName, cellType,
cellValue, cellString, sheet, model)) != 0)
NX_RAISE(IC_SETCELLVALUE, &imxReturnCode, NULL);
}
if ((imxReturnCode = imxUpdateModel(model)) != 0)
NX_RAISE(IC_UPDATE, &imxReturnCode, NULL);
// free stuff
[self freeData:rowNames count:rowCount];
[self freeData:columnNames count:colCount];
NX_HANDLER
switch (NXLocalHandler.code)
{
case IC_GETSELECTION:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_GETINFO:
if (*(int *)NXLocalHandler.data1 == imxerr_ITEM_NOT_FOUND)
myReturnCode = WB_NOSUCHCOLUMN;
else
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_GETCATEGORIES:
free(parent);
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_GETROWS:
free(parent);
break;
case IC_ADDCOLUMNS:
free(parent);
[self freeData:rowNames count:rowCount];
break;
case IC_GETCOLUMNS:
free(parent);
[self freeData:rowNames count:rowCount];
break;
case IC_COLUMNCHECK:
myReturnCode = WB_NOSUCHCOLUMN;
break;
case IC_NUMBERCOLUMNS:
[self freeData:rowNames count:rowCount];
[self freeData:columnNames count:colCount];
myReturnCode = WB_NOTENOUGHCOLUMNS;
break;
case IC_SETCELLVALUE:
case IC_UPDATE:
[self freeData:rowNames count:rowCount];
[self freeData:columnNames count:colCount];
myReturnCode = WB_UNKNOWNERROR;
break;
default:
NX_RERAISE();
}
NX_ENDHANDLER
return myReturnCode;
}
- (int)addColumns:(char **)newColumns count:(int)numColumns
afterColumn:(char *)existingColumn
{
imxSelType selectionType = imxsel_ITEM, oldType;
char *viewName, *sheetName, *modelName, *selection, *view, **columnNames;
int imxReturnCode, myReturnCode = 0, numCols, colIndex;
NX_DURING
// get the view, sheet, and model
if ((imxReturnCode = imxGetSelection(&selection, &oldType,
&viewName, &sheetName, &modelName)) != 0)
NX_RAISE(IC_GETSELECTION, &imxReturnCode, NULL);
view = (char *)malloc(strlen(viewName)+1);
sheet = (char *)realloc(sheet, strlen(sheetName)+1);
model = (char *)realloc(model, strlen(modelName)+1);
strcpy(view, viewName);
strcpy(sheet, sheetName);
strcpy(model, modelName);
// select it the given column
if ((imxReturnCode = imxSetSelection(existingColumn, selectionType,
view, sheet, model)) != 0)
NX_RAISE(IC_SETSELECTION, &imxReturnCode, NULL);
free(view);
// create the new columns
if ((imxReturnCode = imxAddItems(NULL, numColumns, ipos_AFTER)) != 0)
NX_RAISE(IC_ADDITEMS, NULL, NULL);
// rename the new columns
if (newColumns)
{
[self getSelectedColumnNames:&columnNames count:&numCols];
for (colIndex = 0; colIndex < numCols; colIndex++)
if ((imxReturnCode = imxRename(newColumns[colIndex],
imxsel_ITEM, columnNames[colIndex],
sheet, model)) != 0)
NX_RAISE(IC_RENAME, &imxReturnCode, NULL);
[self freeData:columnNames count:numCols];
}
NX_HANDLER
switch (NXLocalHandler.code)
{
case IC_GETSELECTION:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_SETSELECTION:
free(view);
if (*(int *)NXLocalHandler.data1 == imxerr_NO_SELECTION)
myReturnCode = WB_NOSUCHCOLUMN;
else
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_ADDITEMS:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_RENAME:
[self freeData:columnNames count:numCols];
myReturnCode = WB_UNKNOWNERROR;
break;
default:
NX_RERAISE();
}
NX_ENDHANDLER
return myReturnCode;
}
- (int)getSelectedColumnNames:(char ***)columnNames count:(int *)numColumns
{
imxSelType selectionType;
char *viewName, *sheetName, *modelName, *selectionName, *parentName;
int imxReturnCode, myReturnCode = 0;
char *columnList, *selection;
NX_DURING
// get the selection information
if ((imxReturnCode = imxGetSelection(&selectionName, &selectionType,
&viewName, &sheetName, &modelName)) != 0)
NX_RAISE(IC_GETSELECTION, &imxReturnCode, NULL);
sheet = (char *)realloc(sheet, strlen(sheetName)+1);
model = (char *)realloc(model, strlen(modelName)+1);
selection = (char *)malloc(strlen(selectionName)+1);
strcpy(sheet, sheetName);
strcpy(model, modelName);
strcpy(selection, selectionName);
// get a list of the names in the selected range
if (selectionType == imxsel_ITEM)
{
if ((imxReturnCode = imxGetItemRangeInfo(&parentName,
&columnList, selection, sheet, model)) != 0)
NX_RAISE(IC_GETINFO, &imxReturnCode, NULL);
[self getNames:columnNames fromList:columnList count:numColumns];
}
else
NX_RAISE(IC_SELECTIONTYPE, &imxReturnCode, NULL);
free(selection);
NX_HANDLER
switch (NXLocalHandler.code)
{
case IC_GETSELECTION:
if (*(int *)NXLocalHandler.data1 == imxerr_NO_SELECTION)
myReturnCode = WB_NOTHINGSELECTED;
else
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_GETINFO:
free(selection);
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_SELECTIONTYPE:
free(selection);
myReturnCode = WB_WRONGTYPEOFSELECTION;
break;
default:
NX_RERAISE();
}
NX_ENDHANDLER
return myReturnCode;
}
- (int)makeNewWorksheet:(char *)worksheetName numRows:(int)numRows
numCols:(int)numColumns rowNames:(char **)rowNames
colNames:(char **)columnNames
{
imxSelType selectionType;
char *viewName, *sheetName, *modelName, *selection;
int imxReturnCode, myReturnCode = 0;
NX_DURING
// return if number of rows or columns is zero
if ((numRows <= 0) || (numColumns <= 0))
NX_RAISE(IC_BADPARAMETERS, NULL, NULL);
// create the new worksheet, rename it, get the sheet and model names
if ((imxReturnCode = imxCmdExec(imxcmd_NEWSHEET)) != 0)
NX_RAISE(IC_NEWSHEET, &imxReturnCode, NULL);
if ((imxReturnCode = imxGetSelection(&selection, &selectionType,
&viewName, &sheetName, &modelName)) != 0)
NX_RAISE(IC_GETSELECTION, &imxReturnCode, NULL);
sheet = (char *)realloc(sheet, strlen(sheetName)+1);
model = (char *)realloc(model, strlen(modelName)+1);
strcpy(sheet, sheetName);
strcpy(model, modelName);
if (worksheetName)
{
if ((imxReturnCode = imxRename(worksheetName, imxsel_SHEET,
sheet, sheet, model)) != 0)
NX_RAISE(IC_RENAME, &imxReturnCode, NULL);
if ((imxReturnCode = imxGetSelection(&selection, &selectionType,
&viewName, &sheetName, &modelName)) != 0)
NX_RAISE(IC_GETSELECTION, &imxReturnCode, NULL);
sheet = (char *)realloc(sheet, strlen(sheetName)+1);
model = (char *)realloc(model, strlen(modelName)+1);
strcpy(sheet, sheetName);
strcpy(model, modelName);
}
// add and name columns
if (numColumns > 1)
if (columnNames)
{
if ((myReturnCode = [self addColumns:columnNames+1
count:numColumns-1 afterColumn:"B1"]) != 0)
NX_RAISE(IC_ADDCOLUMNS, NULL, NULL);
}
else
if ((myReturnCode = [self addColumns:NULL count:numColumns-1
afterColumn:"B1"]) != 0)
NX_RAISE(IC_ADDCOLUMNS, NULL, NULL);
if (columnNames)
if ((imxReturnCode = imxRename(columnNames[0], imxsel_ITEM,
"B1", sheet, model)) != 0)
NX_RAISE(IC_RENAME, &imxReturnCode, NULL);
// add rows and name rows
if (numRows > 1)
if (rowNames)
{
if ((myReturnCode = [self addColumns:rowNames+1 count:numRows-1
afterColumn:"A1"]) != 0)
NX_RAISE(IC_ADDCOLUMNS, NULL, NULL);
}
else
if ((myReturnCode = [self addColumns:NULL count:numRows-1
afterColumn:"A1"]) != 0)
NX_RAISE(IC_ADDCOLUMNS, NULL, NULL);
if (rowNames)
if ((imxReturnCode = imxRename(rowNames[0], imxsel_ITEM,
"A1", sheet, model)) != 0)
NX_RAISE(IC_RENAME, &imxReturnCode, NULL);
NX_HANDLER
switch (NXLocalHandler.code)
{
case IC_GETSELECTION:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_BADPARAMETERS:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_ADDITEMS:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_NEWSHEET:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_RENAME:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_ADDCOLUMNS:
break;
default:
NX_RERAISE();
}
NX_ENDHANDLER
return myReturnCode;
}
- getNames:(char ***)names fromList:(char *)list count:(int *)numNames
{
int nameIndex;
char *nameStart, *nameEnd;
// splits a \n-separated list into separate strings
for ((*numNames) = 0, nameStart = list; *nameStart;
nameStart = strchr(nameStart, '\n') + 1, (*numNames)++);
*names = (char **)malloc((*numNames) * sizeof(char *));
nameStart = list;
for (nameIndex = 0; nameIndex < *numNames; nameIndex++)
{
nameEnd = strchr(nameStart, '\n');
(*names)[nameIndex] = (char *)malloc(nameEnd - nameStart + 1);
strncpy((*names)[nameIndex], nameStart, nameEnd - nameStart);
(*names)[nameIndex][nameEnd - nameStart] = '\0';
nameStart = nameEnd + 1;
}
return self;
}
- (int)getRows:(char ***)rowList rowCount:(int *)numRows
forColumnCategory:(char *)columnCategory
{
char *lastRow, *firstRow;
char *categoryList, **categoryNames, *rowCategory, *parentName;
char *rowRange, *itemList;
int imxReturnCode, myReturnCode = 0, categoryCount;
NX_DURING
// get a list of all the categories, make sure there aren't more than two
if ((imxReturnCode = imxGetCategoryList(&categoryList, sheet, model))
!= 0)
NX_RAISE(IC_GETCATEGORIES, &imxReturnCode, NULL);
[self getNames:&categoryNames fromList:categoryList
count:&categoryCount];
if (categoryCount > 2)
NX_RAISE(IC_NUMBERCATEGORIES, NULL, NULL);
// find which category contains the given item and which doesn't
if (strcmp(categoryNames[0], columnCategory) == 0)
rowCategory = categoryNames[1];
else
if (strcmp(categoryNames[1], columnCategory) == 0)
rowCategory = categoryNames[0];
else
NX_RAISE(IC_BADCATEGORIES, NULL, NULL);
// for the non-given category, get a list of the items in it
if ((imxReturnCode = imxGetItemInfo(&parentName, &firstRow, &lastRow,
rowCategory, sheet, model)) != 0)
NX_RAISE(IC_GETITEMINFO, &imxReturnCode, NULL);
[self freeData:categoryNames count:categoryCount];
rowRange = (char *)malloc(strlen(firstRow) + strlen(lastRow) + 3);
strcpy(rowRange, firstRow);
strcat(rowRange, "..");
strcat(rowRange, lastRow);
if ((imxReturnCode = imxGetItemRangeInfo(&parentName, &itemList,
rowRange, sheet, model)) != 0)
NX_RAISE(IC_GETRANGEINFO, &imxReturnCode, NULL);
free(rowRange);
[self getNames:rowList fromList:itemList count:numRows];
NX_HANDLER
switch (NXLocalHandler.code)
{
case IC_GETCATEGORIES:
myReturnCode = WB_UNKNOWNERROR;
break;
case IC_NUMBERCATEGORIES:
myReturnCode = WB_TOOMANYCATEGORIES;
[self freeData:categoryNames count:categoryCount];
break;
case IC_BADCATEGORIES:
myReturnCode = WB_NOSUCHCOLUMN;
[self freeData:categoryNames count:categoryCount];
break;
case IC_GETITEMINFO:
myReturnCode = WB_UNKNOWNERROR;
[self freeData:categoryNames count:categoryCount];
break;
case IC_GETRANGEINFO:
myReturnCode = WB_UNKNOWNERROR;
free(rowRange);
break;
default:
NX_RERAISE();
}
NX_ENDHANDLER
return myReturnCode;
}
- (int)handleCell:(int)cellType forData:(int)dataType
{
int handleAs = IC_ERROR;
if (dataType == WB_STRINGDATA)
switch (cellType)
{
case cval_TEXT:
handleAs = IC_USEVALUE;
break;
case cval_EMPTY:
handleAs = IC_USEZERO;
break;
case cval_NUMBER:
handleAs = IC_CONVERT;
break;
default:
handleAs = IC_ERROR;
}
else // data type is numeric
switch (cellType)
{
case cval_NUMBER:
handleAs = IC_USEVALUE;
break;
case cval_TEXT:
switch (textCellHandling)
{
case WB_SKIP:
handleAs = IC_SKIPVALUE;
break;
case WB_ZERO:
handleAs = IC_USEZERO;
break;
case WB_ERROR:
handleAs = IC_ERROR;
}
break;
case cval_EMPTY:
switch (emptyCellHandling)
{
case WB_SKIP:
handleAs = IC_SKIPVALUE;
break;
case WB_ZERO:
handleAs = IC_USEZERO;
break;
case WB_ERROR:
handleAs = IC_ERROR;
}
break;
default:
handleAs = IC_ERROR;
}
return handleAs;
}
- deleteTrailingZeros:(char *)formattedNumber
{
if (strchr(formattedNumber, '.'))
{
while (formattedNumber[strlen(formattedNumber)-1] == '0')
formattedNumber[strlen(formattedNumber)-1] = '\0';
if (formattedNumber[strlen(formattedNumber)-1] == '.')
formattedNumber[strlen(formattedNumber)-1] = '\0';
}
return self;
}
- freeData:(void *)data count:(int)count
{
int index;
for (index = 0; index < count; index++)
free(((char **)data)[index]);
free(data);
return self;
}
- freeStringData:(void *)data counts:(int)count1 :(int)count2
{
int index1, index2;
for (index1 = 0; index1 < count1; index1++)
for (index2 = 0; index2 < count2; index2++)
free(((char ***)data)[index1][index2]);
for (index1 = 0; index1 < count1; index1++)
free(((char ***)data)[index1]);
free(data);
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.