/*************************************************** InsertRow This function inserts a blank row at the specified location. The previous row in that location is pushed down one row. If the specified row does not already exist, then the Insert will fail. Params row - row number where a blank row will be inserted Return UG_SUCCESS - success UG_ERROR - failure ****************************************************/ int CUGMem::InsertRow(long row) { //adjust the linked list if the list has an item at the insertion point if(GotoRow(row)==UG_SUCCESS) { //create a new row information item for the list //then insert it UGMemRI *newrow; newrow = new UGMemRI; newrow->col = NULL; newrow->next = m_rowInfo; newrow->prev = m_rowInfo->prev; newrow->cellLookup = NULL; if(newrow->prev != NULL) newrow->prev->next = newrow; m_rowInfo->prev = newrow; m_currentRow++; return UG_SUCCESS; } else { return UG_ERROR; } }
void CDDBaseGrid::SelectRow(long row) { if (row >= 0 && row < GetNumberRows() && GetNumberCols() > 0) { SetMultiSelectMode(TRUE); GotoRow(row); SelectRange(0, row, (GetNumberCols() - 1), row); } }
/*************************************************** DeleteRow This function deletes a row at the specified position. Even if the row does not exist the function will return success. Params row - row number to delete Return UG_SUCCESS - success ****************************************************/ int CUGMem::DeleteRow(long row) { //adjust the linked list if the list has an item at the insertion point if(GotoRow(row)==UG_SUCCESS) { //delete the columns for this row UGMemCI *next; while(PrevCol()==UG_SUCCESS); //find the first col while(m_colInfo != NULL) //delete the cols to the end { next = m_colInfo->next; //delete the colinfo if(m_colInfo->cell != NULL) delete m_colInfo->cell; delete m_colInfo; m_colInfo = next; } //update the row links UGMemRI *currentrow; if(m_rowInfo->prev != NULL) m_rowInfo->prev->next = m_rowInfo->next; if(m_rowInfo->next != NULL) { m_rowInfo->next->prev = m_rowInfo->prev; currentrow = m_rowInfo->next; } else if(m_rowInfo->prev != NULL) { currentrow = m_rowInfo->prev; m_currentRow--; } else { currentrow = NULL; m_currentRow = 0; } delete m_rowInfo; m_rowInfo = currentrow; //update the current column pointer if(m_rowInfo != NULL) m_colInfo = m_rowInfo->col; else m_colInfo = NULL; m_currentCol = 0; return UG_SUCCESS; } //return success even if there are no rows to delete //since the memory manager is autoupdating return UG_SUCCESS; }
/*************************************************** GetPrevNonBlankCol Returns the previous column (relative to the given column) that is not a blank cell. This function is usally used to determine how cell overlapping is performed. Params col - [in] column number to start the search from [out] column number of the previous non-blank column row - row number to perform the search on Return UG_SUCCESS - success UG_ERROR - failure ****************************************************/ int CUGMem::GetPrevNonBlankCol(int *col,long row) { //move to the row if not already there if(m_currentRow != row) { if(GotoRow(row) != UG_SUCCESS) //no cells on the specified row { return UG_ERROR; } } //move to the col if not already there if(m_currentCol != *col) { //if the specified col was not found then 1 is returned by //GotoCol, but it will find the closest col if(GotoCol(*col) != UG_SUCCESS) { //if the first cell found is blank then there is no prev if(m_colInfo == NULL) { return UG_ERROR; } if(m_colInfo->cell == NULL) { return UG_ERROR; } } } //if there is no col information for the row then there is no prev col if(m_colInfo == NULL) return UG_ERROR; // if the specified cell (or a prev cell in the same row was found // then find the prev non-blank cell UGMemCI * tempCI = m_colInfo; int tempCol = m_currentCol; //main prev search loop while(tempCol >= 0) { if(tempCI->cell != NULL && *col != tempCol){ if(tempCI->cell->GetTextLength() > 0){ *col = tempCol; return UG_SUCCESS; } } tempCI = tempCI->prev; tempCol --; } return UG_ERROR; }
/*************************************************** DeleteCol This function deletes a cell at the specified location. Even if the cell does not exist the function will return success. However if there are no rows in the grid the function will fail. Params col - column number of cell to delete row - row number of cell to delete Return UG_SUCCESS - success UG_ERROR - failure ****************************************************/ int CUGMem::DeleteCell(int col,long row) { if(GotoRow(row)==UG_SUCCESS) { if(GotoCol(col)==UG_SUCCESS) { //delete the colinfo cell object if(m_colInfo->cell != NULL) { m_colInfo->cell->ClearMemory(); delete m_colInfo->cell; m_colInfo->cell = NULL; } m_colInfo = m_rowInfo->col; m_currentCol = 0; return UG_SUCCESS; } } return UG_ERROR; }
/*************************************************** GetNumRows Returns the number of rows allocated in the memory datasource. This number may not be the same as the number of rows shown in the grid (see CUGCtrl::GetNumRows). This function only returns the number of rows that have been allocated in the memory datasource. Params none Return the number of allocated rows ****************************************************/ long CUGMem::GetNumRows() { //find the highest row number GotoRow(0x7FFFFFFF); return m_currentRow; }
int CUGMem::SortBy(long startRow, long endRow, int *cols,int numCols,int flags) { if(m_rowInfo == NULL) return UG_ERROR; if(startRow >= endRow) return UG_ERROR; UGMemRI *OldListRowInfo; UGMemRI *OldListNextRowInfo; UGMemRI *NewListRowInfo; UGMemRI *NewListStartRowInfo; UGMemRI *NewListRowInfo_HalfPt; CUGCell* cell1; CUGCell* cell2; CUGCell blankCell; int index; int rt; BOOL bInserted = FALSE; int halfPtOffset = 0; BOOL bSkip; UGMemRI* lastSkipRow; long rowCount = startRow; //goto the first row, and copy the first row over to the sorted list GotoRow(startRow); NewListRowInfo = m_rowInfo; NewListStartRowInfo = m_rowInfo; NewListRowInfo_HalfPt = NewListRowInfo; //goto the second row and make that the unsorted list OldListRowInfo = m_rowInfo->next; m_rowInfo->next = NULL; //copy the (pointers to) cells from the columns to be sorted into the lookup list NewListRowInfo->cellLookup = new CUGCell*[numCols]; m_colInfo = NewListRowInfo->col; m_currentCol = 0; // TD JF added (for init as below) for(index =0; index < numCols;index++){ if(GotoCol(cols[index])==UG_SUCCESS) NewListRowInfo->cellLookup[index] = m_colInfo->cell; else NewListRowInfo->cellLookup[index] = NULL; } //main row sort loop - while there are items in the unsorted list while(OldListRowInfo != NULL && (rowCount < endRow) ){ //save the next row pointer OldListNextRowInfo = OldListRowInfo->next; //copy the (pointers to) cells from the columns to be sorted into the lookup list OldListRowInfo->cellLookup = new CUGCell*[numCols]; m_colInfo = OldListRowInfo->col; m_currentCol = 0; for(index =0; index < numCols;index++){ if(GotoCol(cols[index])==UG_SUCCESS) { OldListRowInfo->cellLookup[index] = m_colInfo->cell; } else { OldListRowInfo->cellLookup[index] = NULL; } } //check the half point //================================================ //get a cell from the unsorted list if(OldListRowInfo->cellLookup[0] != NULL) cell1 = OldListRowInfo->cellLookup[0]; else{ blankCell.ClearAll(); blankCell.ClearMemory(); cell1 = &blankCell; } //get a cell from the sorted list if(NewListRowInfo_HalfPt->cellLookup[0] != NULL) cell2 = NewListRowInfo_HalfPt->cellLookup[0]; else{ blankCell.ClearAll(); blankCell.ClearMemory(); cell2 = &blankCell; } //call the evaluation function rt = m_ctrl->OnSortEvaluate(cell1,cell2,flags); if(rt <= 0){ NewListRowInfo = NewListStartRowInfo; halfPtOffset -=1; } else{ NewListRowInfo = NewListRowInfo_HalfPt; halfPtOffset +=1; } if(halfPtOffset == -2){ halfPtOffset = 0; if(NewListRowInfo_HalfPt->prev != NULL) if(NewListRowInfo_HalfPt->prev->cellLookup != NULL) NewListRowInfo_HalfPt = NewListRowInfo_HalfPt->prev; } if(halfPtOffset == 2){ halfPtOffset = 0; if(NewListRowInfo_HalfPt->next != NULL) NewListRowInfo_HalfPt = NewListRowInfo_HalfPt->next; } //================================================ bSkip = TRUE; lastSkipRow = NULL; //main loop to check an unsorted item against the sorted list //NewListRowInfo = NewListStartRowInfo; bInserted = FALSE; while(NewListRowInfo != NULL){ //sort by the columns in their given order for(index = 0; index < numCols; index++){ //get a cell from the unsorted list if(OldListRowInfo->cellLookup[index] != NULL) cell1 = OldListRowInfo->cellLookup[index]; else{ blankCell.ClearAll(); blankCell.ClearMemory(); cell1 = &blankCell; } //get a cell from the sorted list if(NewListRowInfo->cellLookup[index] != NULL) cell2 = NewListRowInfo->cellLookup[index]; else{ blankCell.ClearAll(); blankCell.ClearMemory(); cell2 = &blankCell; } //call the evaluation function rt = m_ctrl->OnSortEvaluate(cell1,cell2,flags); if(rt < 0){ if(bSkip && lastSkipRow != NULL){ NewListRowInfo = lastSkipRow; bSkip = FALSE; break; } OldListRowInfo->next = NewListRowInfo; OldListRowInfo->prev = NewListRowInfo->prev; NewListRowInfo->prev = OldListRowInfo; if(OldListRowInfo->prev !=NULL) OldListRowInfo->prev->next = OldListRowInfo; if(NewListRowInfo == NewListStartRowInfo) NewListStartRowInfo = OldListRowInfo; bInserted = TRUE; rowCount++; break; } //if equal then check the next column to sort by else if(rt == 0){ } else{ break; } } //if the item was inserted into the sorted then then break if(bInserted == TRUE) break; //if at the end of the sorted list then add the item if(NewListRowInfo->next == NULL){ NewListRowInfo->next = OldListRowInfo; OldListRowInfo->prev = NewListRowInfo; OldListRowInfo->next = NULL; rowCount++; break; } //perform row skips if(bSkip){ lastSkipRow = NewListRowInfo; for(int loop = 0; loop< 100; loop++){ if(NewListRowInfo->next != NULL){ NewListRowInfo = NewListRowInfo->next; } else{ NewListRowInfo = lastSkipRow; bSkip = FALSE; break; } } } else{ NewListRowInfo = NewListRowInfo->next; } } OldListRowInfo = OldListNextRowInfo; } //reset the linked list positioning pointers m_currentRow = startRow; m_currentCol = 0; m_rowInfo = NewListStartRowInfo; m_colInfo = NewListStartRowInfo->col; //add the rest of the rows, if they were not part of the sort if(rowCount == endRow && OldListRowInfo != NULL){ GotoRow(endRow); m_rowInfo->next = OldListRowInfo; OldListRowInfo->prev = m_rowInfo; m_currentRow = startRow; m_rowInfo = NewListStartRowInfo; } //delete all of the cell lookups GotoRow(0); do { if(m_rowInfo->cellLookup != NULL) { delete[] m_rowInfo->cellLookup; } m_rowInfo->cellLookup = NULL; }while(NextRow() == UG_SUCCESS); GotoRow(0); return UG_SUCCESS; }
/*************************************************** FindNext Returns the column and row numbers of the next cell that matches the given string. How the match is performed is dependant on the specified flags. Params string - string to find col - [in] column to start to perform the search on. If searching all columns, then this specifies the column to continue the search from. [out] pointer to the column number of the cell that matches row - [in] row number to start searching from [out] pointer to the row number of the cell that matches flags - flags that modify how the find is performed UG_FIND_CASEINSENSITIVE - all matching is insensitive UG_FIND_PARTIAL - matches all cells that contains the search string as a substring, otherwise the strings must match exactly UG_FIND_ALLCOLUMNS - searches all columns in the grid UG_FIND_UP - search upwards from the specified row, the default search is down. Return UG_SUCCESS - success UG_ERROR - failure ****************************************************/ int CUGMem::FindNext(CString *string,int *col,long *row,int flags) { BOOL success = FALSE; CString tempStr; //goto the first col/row m_findRow = *row; m_findCol = *col; long lastRow = m_ctrl->GetNumberRows()-1; int lastCol = m_ctrl->GetNumberCols()-1; long searchLimit = lastRow+2; // search with wrap long rowCount = 0; BOOL colsDone = FALSE; // note: there could conceivably be a mismatch // here. Not all columns of the grid are necessarily // bound to this datasource. On the other hand, this // does limit us to searching that subset of the // the ds shown on the grid. (assuming col translation // has not been applied to intevening rows...) if(flags&UG_FIND_CASEINSENSITIVE) string->MakeUpper(); // do this once // initial positioning if(flags&UG_FIND_ALLCOLUMNS) { if((flags&UG_FIND_UP)) { m_findCol--; if(m_findCol < 0) { m_findCol = lastCol; m_findRow--; if(m_findRow < 0) m_findRow = lastRow; } } else { m_findCol++; if(m_findCol > lastCol) { m_findCol = 0; m_findRow++; if(m_findRow > lastRow) m_findRow = 0; } } } else { if(!(flags&UG_FIND_UP)) { m_findRow++; if(m_findRow > lastRow) m_findRow = 0; } else { m_findRow--; if(m_findRow < 0) m_findRow = lastRow; } } // end initial positioning // loop through all rows plus wrap one row while(1) { if(rowCount >= searchLimit) return UG_ERROR; if(GotoRow(m_findRow) != UG_SUCCESS) { // goto next row if(!(flags&UG_FIND_UP)) { m_findRow++; if(m_findRow > lastRow) m_findRow = 0; } else { m_findRow--; if(m_findRow < 0) m_findRow = lastRow; } // increment count rowCount++; continue; } // ok - if we get here, the row is valid. Now, find a valid col colsDone = FALSE; while(!colsDone) { if(GotoCol(m_findCol) == UG_SUCCESS) { if(NULL != m_colInfo->cell) { // check for match if(flags&UG_FIND_CASEINSENSITIVE) { if(flags&UG_FIND_PARTIAL) { tempStr = m_colInfo->cell->GetText(); tempStr.MakeUpper(); if( tempStr.Find(*string) >= 0 ) success = TRUE; } else { tempStr = m_colInfo->cell->GetText(); if( tempStr.IsEmpty() == 0 ) { if( string->CompareNoCase( tempStr ) == 0 ) success = TRUE; } } } else { if(flags&UG_FIND_PARTIAL) { tempStr = m_colInfo->cell->GetText(); if( tempStr.Find(*string) >= 0 ) success = TRUE; } else { tempStr = m_colInfo->cell->GetText(); if( tempStr.IsEmpty() == 0 ) { if( string->Compare( tempStr ) == 0 ) success = TRUE; } } } if(success) { *col = m_findCol; *row = m_findRow; return UG_SUCCESS; } } } // move to next col and/or row if(flags&UG_FIND_ALLCOLUMNS) { if((flags&UG_FIND_UP)) { m_findCol--; if(m_findCol < 0) { colsDone = TRUE; m_findCol = lastCol; m_findRow--; rowCount++; if(m_findRow < 0) m_findRow = lastRow; } } else { m_findCol++; if(m_findCol > lastCol) { colsDone = TRUE; m_findCol = 0; m_findRow++; rowCount++; if(m_findRow > lastRow) m_findRow = 0; } } } else { colsDone = TRUE; if(flags&UG_FIND_UP) { m_findRow--; rowCount++; if(m_findRow < 0) m_findRow = lastRow; } else { m_findRow++; rowCount++; if(m_findRow > lastRow) m_findRow = 0; } } } // end while(!colsDone) } // end while(1) // failed to find match... return UG_ERROR; }