Changeset 55
- Timestamp:
- Apr 6, 2001, 7:12:11 PM (24 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/helpers/dosh.h
r54 r55 43 43 BOOL doshQueryShiftState(VOID); 44 44 45 BOOLdoshIsWarp4(VOID);45 ULONG doshIsWarp4(VOID); 46 46 47 47 PSZ doshQuerySysErrorMsg(APIRET arc); … … 297 297 298 298 PSZ doshCreateBackupFileName(const char* pszExisting); 299 300 APIRET doshCreateTempFileName(PSZ pszTempFileName, 301 const char *pcszDir, 302 const char *pcszPrefix, 303 const char *pcszExt); 299 304 300 305 APIRET doshWriteTextFile(const char* pszFile, -
trunk/include/helpers/tree.h
r54 r55 178 178 void *treeLast (TREE *tree); 179 179 180 TREE** treeBuildArray(TREE* pRoot, 181 unsigned long *pulCount); 182 180 183 // Return codes 181 184 #define TREE_OK 0 -
trunk/src/helpers/dialog.c
r54 r55 157 157 typedef struct _ROWDEF 158 158 { 159 PTABLEDEF pOwningTable; // table whose linked list this row belongs to 160 161 LINKLIST llColumns; // contains COLUMNDEF structs, no auto-free 159 PTABLEDEF pOwningTable; // table whose linked list this row belongs to 160 161 LINKLIST llColumns; // contains COLUMNDEF structs, no auto-free 162 163 ULONG flRowFormat; // one of: 164 // -- ROW_VALIGN_BOTTOM 0x0000 165 // -- ROW_VALIGN_CENTER 0x0001 166 // -- ROW_VALIGN_TOP 0x0002 162 167 163 168 CONTROLPOS cpRow; … … 188 193 { 189 194 PROCESS_CALC_SIZES, // step 1 190 PROCESS_CALC_POSITIONS, // step 2191 PROCESS_CREATE_CONTROLS // step 3195 PROCESS_CALC_POSITIONS, // step 3 196 PROCESS_CREATE_CONTROLS // step 4 192 197 } PROCESSMODE; 193 198 … … 212 217 213 218 VOID CalcAutoSizeText(PCONTROLDEF pControlDef, 219 BOOL fMultiLine, // in: if TRUE, multiple lines 214 220 PSIZEL pszlAuto, // out: computed size 215 221 PDLGPRIVATE pDlgData) … … 265 271 if (pControlDef->pcszText) 266 272 { 267 POINTL aptl[TXTBOX_COUNT]; 268 GpiQueryTextBox(pDlgData->hps, 269 strlen(pControlDef->pcszText), 270 (PCH)pControlDef->pcszText, 271 TXTBOX_COUNT, 272 aptl); 273 pszlAuto->cx = aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_BOTTOMLEFT].x; 273 // do we have multiple lines? 274 if (fMultiLine) 275 { 276 RECTL rcl = {0, 0, 1000, 1000}; 277 winhDrawFormattedText(pDlgData->hps, 278 &rcl, 279 pControlDef->pcszText, 280 DT_LEFT | DT_TOP | DT_WORDBREAK | DT_QUERYEXTENT); 281 pszlAuto->cx = rcl.xRight - rcl.xLeft; 282 pszlAuto->cy = rcl.yTop - rcl.yBottom; 283 } 284 else 285 { 286 POINTL aptl[TXTBOX_COUNT]; 287 GpiQueryTextBox(pDlgData->hps, 288 strlen(pControlDef->pcszText), 289 (PCH)pControlDef->pcszText, 290 TXTBOX_COUNT, 291 aptl); 292 pszlAuto->cx = aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_BOTTOMLEFT].x; 293 } 274 294 } 275 295 } … … 292 312 case 0xffff0003L: // WC_BUTTON: 293 313 CalcAutoSizeText(pControlDef, 314 FALSE, // no multiline 294 315 pszlAuto, 295 316 pDlgData); … … 316 337 if (pControlDef->flStyle & SS_TEXT) 317 338 CalcAutoSizeText(pControlDef, 339 ((pControlDef->flStyle & DT_WORDBREAK) != 0), 318 340 pszlAuto, 319 341 pDlgData); … … 384 406 pColumnDef->pOwningRow = pOwningRow; 385 407 386 // for PROCESS_CALC_SIZES: have control return its size387 // plus spacings into szlControl388 // for PROCESS_CALC_POSITIONS: have control compute its389 // position from the column position (there may be390 // spacings)391 // for PROCESS_CREATE_CONTROLS: well, create the control392 408 switch (ProcessMode) 393 409 { 410 /* 411 * PROCESS_CALC_SIZES: 412 * step 1. 413 */ 414 394 415 case PROCESS_CALC_SIZES: 395 416 { … … 454 475 break; } 455 476 477 /* 478 * PROCESS_CALC_POSITIONS: 479 * step 2. 480 */ 481 456 482 case PROCESS_CALC_POSITIONS: 457 483 { … … 459 485 ULONG ulSpacing = 0; 460 486 461 // column position = *plX 487 // column position = *plX on ProcessRow stack 462 488 pColumnDef->cpColumn.x = *plX; 463 489 pColumnDef->cpColumn.y = pOwningRow->cpRow.y; 490 491 // check vertical alignment of row; 492 // we might need to increase column y 493 switch (pOwningRow->flRowFormat & ROW_VALIGN_MASK) 494 { 495 // case ROW_VALIGN_BOTTOM: // do nothing 496 497 case ROW_VALIGN_CENTER: 498 if (pColumnDef->cpColumn.cy < pOwningRow->cpRow.cy) 499 pColumnDef->cpColumn.y 500 += ( (pOwningRow->cpRow.cy - pColumnDef->cpColumn.cy) 501 / 2); 502 break; 503 504 case ROW_VALIGN_TOP: 505 if (pColumnDef->cpColumn.cy < pOwningRow->cpRow.cy) 506 pColumnDef->cpColumn.y 507 += (pOwningRow->cpRow.cy - pColumnDef->cpColumn.cy); 508 break; 509 } 464 510 465 511 if (pColumnDef->fIsNestedTable) … … 481 527 *plX += pColumnDef->cpColumn.cx; 482 528 483 // calculate controlpos by applying spacing529 // calculate CONTROL pos from COLUMN pos by applying spacing 484 530 pColumnDef->cpControl.x = pColumnDef->cpColumn.x 485 531 + ulSpacing; … … 499 545 } 500 546 break; } 547 548 /* 549 * PROCESS_CREATE_CONTROLS: 550 * step 3. 551 */ 501 552 502 553 case PROCESS_CREATE_CONTROLS: … … 1176 1227 lstInit(&pCurrentRow->llColumns, FALSE); 1177 1228 1229 pCurrentRow->flRowFormat = pItemThis->ulData; 1230 1178 1231 lstAppendItem(&pCurrentTable->llRows, pCurrentRow); 1179 1232 } -
trunk/src/helpers/dosh.c
r54 r55 144 144 } 145 145 146 147 146 /* 148 147 *@@ doshIsWarp4: 149 * returns TRUE only if at least OS/2 Warp 4 is running. 148 * checks the OS/2 system version number. 149 * 150 * Returns: 151 * 152 * -- 0 (FALSE): OS/2 2.x or Warp 3 is running. 153 * 154 * -- 1: Warp 4.0 is running. 155 * 156 * -- 2: Warp 4.5 is running (WSeB or Warp 4 FP 13+ or eCS 157 * or ACP/MCP), or even something newer. 150 158 * 151 159 *@@changed V0.9.2 (2000-03-05) [umoeller]: reported TRUE on Warp 3 also; fixed 152 160 *@@changed V0.9.6 (2000-10-16) [umoeller]: patched for speed 153 */ 154 155 BOOL doshIsWarp4(VOID) 156 { 157 static BOOL s_brc = FALSE; 158 static BOOL s_fQueried = FALSE; 161 *@@changed V0.9.9 (2001-04-04) [umoeller]: now returning 2 for Warp 4.5 and above 162 */ 163 164 ULONG doshIsWarp4(VOID) 165 { 166 static BOOL s_fQueried = FALSE; 167 static ULONG s_ulrc = 0; 168 159 169 if (!s_fQueried) 160 170 { … … 170 180 171 181 if ( (aulBuf[0] > 20) // major > 20; not the case with Warp 3, 4, 5 172 || ( (aulBuf[0] == 20) // major == 20 and minor >= 4 0173 && (aulBuf[1] >= 4 0)182 || ( (aulBuf[0] == 20) // major == 20 and minor >= 45 183 && (aulBuf[1] >= 45) 174 184 ) 175 185 ) 176 s_brc = TRUE; 186 // Warp 4.5 or newer: 187 s_ulrc = 2; 188 else if ( (aulBuf[0] == 20) // major == 20 and minor == 40 189 && (aulBuf[1] == 40) 190 ) 191 // Warp 4: 192 s_ulrc = 1; 177 193 178 194 s_fQueried = TRUE; 179 195 } 180 196 181 return (s_ brc);197 return (s_ulrc); 182 198 } 183 199 … … 1142 1158 1143 1159 return (strdup(szFilename)); 1160 } 1161 1162 /* 1163 *@@ doshCreateTempFileName: 1164 * produces a file name in the the specified directory 1165 * or $(TEMP) which presently doesn't exist. This 1166 * checks the directory for existing files, but does 1167 * not open the temp file. 1168 * 1169 * If (pcszDir != NULL), we look into that directory. 1170 * Otherwise we look into the directory specified 1171 * by the $(TEMP) environment variable. 1172 * If $(TEMP) is not set, $(TMP) is tried next. 1173 * 1174 * If the directory thus specified does not exist, the 1175 * root directory of the boot drive is used instead. 1176 * As a result, this function should be fairly bomb-proof. 1177 * 1178 * If (pcszExt != NULL), the temp file receives 1179 * that extension, or no extension otherwise. 1180 * Do not specify the dot in pcszExt. 1181 * 1182 * pszTempFileName receives the fully qualified 1183 * file name of the temp file in that directory 1184 * and must point to a buffer CCHMAXPATH in size. 1185 * The file name is 8+3 compliant if pcszExt does 1186 * not exceed three characters. 1187 * 1188 * If (pcszPrefix != NULL), the temp file name 1189 * is prefixed with pcszPrefix. Since the temp 1190 * file name must not exceed 8+3 letters, we 1191 * can only use ( 8 - strlen(pcszPrefix ) digits 1192 * for a random number to make the temp file name 1193 * unique. You must therefore use a maximum of 1194 * four characters for the prefix. Otherwise 1195 * ERROR_INVALID_PARAMETER is returned. 1196 * 1197 * Example: Assuming TEMP is set to C:\TEMP, 1198 + 1199 + dosCreateTempFileName(szBuffer, 1200 + NULL, // use $(TEMP) 1201 + "pre", // prefix 1202 + "tmp") // extension 1203 + 1204 * would produce something like "C:\TEMP\pre07FG2.tmp". 1205 * 1206 *@@added V0.9.9 (2001-04-04) [umoeller] 1207 */ 1208 1209 APIRET doshCreateTempFileName(PSZ pszTempFileName, // out: fully q'fied temp file name 1210 const char *pcszDir, // in: dir or NULL for %TEMP% 1211 const char *pcszPrefix, // in: prefix for temp file or NULL 1212 const char *pcszExt) // in: extension (without dot) or NULL 1213 { 1214 APIRET arc = NO_ERROR; 1215 1216 ULONG ulPrefixLen = (pcszPrefix) 1217 ? strlen(pcszPrefix) 1218 : 0; 1219 1220 if ( (!pszTempFileName) 1221 || (ulPrefixLen > 4) 1222 ) 1223 arc = ERROR_INVALID_PARAMETER; 1224 else 1225 { 1226 CHAR szDir[CCHMAXPATH] = ""; 1227 FILESTATUS3 fs3; 1228 1229 const char *pcszTemp = pcszDir; 1230 1231 if (!pcszTemp) 1232 { 1233 pcszTemp = getenv("TEMP"); 1234 if (!pcszTemp) 1235 pcszTemp = getenv("TMP"); 1236 } 1237 1238 if (pcszTemp) // either pcszDir or $(TEMP) or $(TMP) now 1239 if (DosQueryPathInfo((PSZ)pcszTemp, 1240 FIL_STANDARD, 1241 &fs3, 1242 sizeof(fs3))) 1243 // TEMP doesn't exist: 1244 pcszTemp = NULL; 1245 1246 if (!pcszTemp) 1247 // not set, or doesn't exist: 1248 // use root directory on boot drive 1249 sprintf(szDir, 1250 "%c:\\", 1251 doshQueryBootDrive()); 1252 else 1253 { 1254 strcpy(szDir, pcszTemp); 1255 if (szDir[strlen(szDir) - 1] != '\\') 1256 strcat(szDir, "\\"); 1257 } 1258 1259 if (!szDir[0]) 1260 arc = ERROR_PATH_NOT_FOUND; // shouldn't happen 1261 else 1262 { 1263 ULONG ulRandom = 0; 1264 ULONG cAttempts = 0; 1265 1266 // produce random number 1267 DosQuerySysInfo(QSV_MS_COUNT, 1268 QSV_MS_COUNT, 1269 &ulRandom, 1270 sizeof(ulRandom)); 1271 1272 do 1273 { 1274 CHAR szFile[20] = "", 1275 szFullTryThis[CCHMAXPATH]; 1276 1277 // use the lower eight hex digits of the 1278 // system uptime as the temp dir name 1279 sprintf(szFile, 1280 "%08lX", 1281 ulRandom & 0xFFFFFFFF); 1282 1283 // if prefix is specified, overwrite the 1284 // first characters in the random number 1285 if (pcszPrefix) 1286 memcpy(szFile, pcszPrefix, ulPrefixLen); 1287 1288 if (pcszExt) 1289 { 1290 szFile[8] = '.'; 1291 strcpy(szFile + 9, pcszExt); 1292 } 1293 1294 // now compose full temp file name 1295 strcpy(szFullTryThis, szDir); 1296 strcat(szFullTryThis, szFile); 1297 // now we have: "C:\temp\wpiXXXXX" 1298 if (DosQueryPathInfo(szFullTryThis, 1299 FIL_STANDARD, 1300 &fs3, 1301 sizeof(fs3)) 1302 == ERROR_FILE_NOT_FOUND) 1303 { 1304 // file or dir doesn't exist: 1305 // cool, we're done 1306 strcpy(pszTempFileName, szFullTryThis); 1307 return (NO_ERROR); 1308 } 1309 1310 // if this didn't work, raise ulRandom and try again 1311 ulRandom += 123; 1312 1313 // try only 100 times, just to be sure 1314 cAttempts++; 1315 } while (cAttempts < 100); 1316 1317 // 100 loops elapsed: 1318 arc = ERROR_BAD_FORMAT; 1319 } 1320 } 1321 1322 return (arc); 1144 1323 } 1145 1324 -
trunk/src/helpers/dosh2.c
r54 r55 1789 1789 */ 1790 1790 1791 int Compare(const void *key,1792 const void *element)1791 int _Optlink Compare(const void *key, 1792 const void *element) 1793 1793 { 1794 1794 USHORT usOrdinal = *((PUSHORT) key); … … 1865 1865 &ulDummy))) 1866 1866 { 1867 if ((pFunction = bsearch(&usOrdinal,1868 paFunctions,1869 cFunctions,1870 sizeof(FSYSFUNCTION),1871 Compare)))1867 if ((pFunction = (PFSYSFUNCTION)bsearch(&usOrdinal, 1868 paFunctions, 1869 cFunctions, 1870 sizeof(FSYSFUNCTION), 1871 Compare))) 1872 1872 { 1873 1873 memcpy(pFunction->achFunctionName, -
trunk/src/helpers/except.c
r32 r55 16 16 * especially applies to multi-thread programs using 17 17 * mutex semaphores (more on that below). The functions 18 * and macros in here are designed to make that more simple. 19 * 20 * The macros in except.h automatically insert code for properly 21 * registering and deregistering the handlers in except.c. You 22 * should ALWAYS use these macros instead of directly registering 23 * the handlers to avoid accidentally forgetting to deregister 24 * them. If you forget to deregister an exception handler, this 25 * can lead to really strange errors (crashes, hangs) which are 26 * nearly impossible to debug because the thread's stack space 27 * might get completely messed up. 28 * 29 * The general idea of these macros is to define TRY / CATCH 30 * blocks similar to C++. If an exception occurs in the TRY block, 31 * execution is transferred to the CATCH block. (This works in both 32 * C and C++, by the way.) 33 * 34 * The "OnKill" function that was added with V0.9.0 has been 35 * removed again with V0.9.7. Use DosEnterMustComplete instead. 36 * Details follow. 18 * and macros in here are designed to make that more 19 * simple. 20 * 21 * The macros in except.h automatically insert code for 22 * properly registering and deregistering the handlers 23 * in except.c. You should ALWAYS use these macros 24 * instead of directly registering the handlers to avoid 25 * accidentally forgetting to deregister them. If you 26 * forget to deregister an exception handler, this can 27 * lead to really strange errors (crashes, hangs) which 28 * are nearly impossible to debug because the thread's 29 * stack probably got completely messed up. 30 * 31 * The general idea of these macros is to define 32 * TRY / CATCH blocks similar to C++. If an exception 33 * occurs in the TRY block, execution is transferred to 34 * the CATCH block. (This works in both C and C++, by the 35 * way.) 36 * 37 * The "OnKill" function that was added with V0.9.0 has 38 * been removed again with V0.9.7. 37 39 * 38 40 * The general usage is like this: … … 42 44 + TRY_LOUD(excptid) // or: TRY_QUIET(excptid) 43 45 + { 46 + char *p = NULL; 47 + 44 48 + .... // the stuff in here is protected by 45 49 + // the excHandlerLoud or excHandlerQuiet 46 50 + // exception handler 51 + *p = "A"; 47 52 + } 48 53 + CATCH(excptid) … … 58 63 * exception occurs. 59 64 * The CATCH block is _required_ even if you do nothing 60 * in there. 65 * in there, because the CATCH() macro will deregister 66 * the handler. 61 67 * 62 68 * "excptid" can be any C identifier which is not used in … … 78 84 * get called. So if you enclose your main() code in a 79 85 * TRY_* block, your entire application is protected. 86 * If any subfunction fails, execution is transferred to 87 * the closest CATCH() that was installed (as with C++ 88 * try and catch). 80 89 * 81 90 * <B>Asynchronous exceptions</B> … … 83 92 * The exception handlers in this file (which are installed 84 93 * with the TRY/CATCH mechanism) only intercept synchronous 85 * exceptions (see excHandlerLoud for a list). They do not 86 * protect your code against asynchronous exceptions. 94 * exceptions, most importantly, XCPT_ACCESS_VIOLATION (see 95 * excHandlerLoud for a list). They do not protect your code 96 * against asynchronous exceptions. 87 97 * 88 98 * OS/2 defines asynchronous exceptions to be those that … … 100 110 * 101 111 * The problem with OS/2 mutex semaphores is that they are 102 * not automatically released when a thread terminates. 103 * If the thread owning the mutex died without releasing 104 * the mutex, other threads which are blocked on that mutex 105 * will wait forever and become zombie threads. Even worse, 106 * if this happens to a PM thread, this will hang the system. 107 * 108 * Here's the typical scenario with two threads: 109 * 110 * 1) Thread 2 requests a mutex and does lots of processing. 111 * 112 * 2) Thread 1 requests the mutex. Since it's still owned 113 * by thread 2, thread 1 blocks. 114 * 115 * 3) Thread 2 crashes in its processing. Without an 116 * exception handler, OS/2 will terminate the process. 117 * It will first kill thread 2 and then attempt to 118 * kill thread 1. This fails because it is still 119 * blocking on the semaphore that thread 2 never 120 * released. Boom. 121 * 122 * The same scenario happens when a process gets killed. 123 * Since OS/2 will kill secondary threads before thread 1, 124 * the same situation can arise. 125 * 126 * As a result, you must protect any section of code which 127 * requests a semaphore _both_ against crashes _and_ 128 * termination. 112 * sometimes not automatically released when a thread terminates. 113 * If there are several mutexes involved and they are released 114 * in improper order, you can get zombie threads on exit. 115 * Even worse, if this happens to a PM thread, this will hang 116 * the system. 117 * 118 * As a result, you should protect any section of code which 119 * requests a semaphore with the exception handlers. To protect 120 * yourself against thread termination, use must-complete 121 * sections as well (but be careful with those if your code 122 * takes a long time to execute... but then you shouldn't 123 * request a mutex in the first place). 129 124 * 130 125 * So _whenever_ you request a mutex semaphore, enclose … … 141 136 + 142 137 + DosEnterMustComplete(&ulNesting); 143 + TRY_QUIET(excpt1 , OnKillYourFunc)// or TRY_LOUD138 + TRY_QUIET(excpt1) // or TRY_LOUD 144 139 + { 145 + fSemOwned = (WinRequestMutexSem(hmtx, ...) == NO_ERROR);140 + fSemOwned = !WinRequestMutexSem(hmtx, ...); 146 141 + if (fSemOwned) 147 142 + { ... // work on your protected data 148 143 + } 144 + // mutex gets released below 149 145 + } 150 146 + CATCH(excpt1) { } END_CATCH(); // always needed! 151 147 + 152 + if (fSemOwned) { 148 + if (fSemOwned) 149 + { 153 150 + // this gets executed always, even if an exception occured 154 151 + DosReleaseMutexSem(hmtx); -
trunk/src/helpers/stringh.c
r54 r55 1190 1190 * 1191 1191 *@@added V0.9.0 [umoeller] 1192 *@@changed V0.9.9 (2001-04-04) [umoeller]: this failed on "123" strings in quotes, fixed 1192 1193 */ 1193 1194 … … 1198 1199 PSZ pParam; 1199 1200 if ((pParam = strhFindAttribValue(pszSearchIn, pszTag))) 1201 { 1202 if ( (*pParam == '\"') 1203 || (*pParam == '\'') 1204 ) 1205 pParam++; // V0.9.9 (2001-04-04) [umoeller] 1206 1200 1207 sscanf(pParam, "%ld", pl); 1208 } 1201 1209 1202 1210 return (pParam); -
trunk/src/helpers/tree.c
r54 r55 1097 1097 } 1098 1098 1099 1099 /* 1100 *@@ treeBuildArray: 1101 * builds an array of TREE* pointers containing 1102 * all tree items in sorted order. 1103 * 1104 * This returns a TREE** pointer to the array. 1105 * Each item in the array is a TREE* pointer to 1106 * the respective tree item. 1107 * 1108 * The array has been allocated using malloc() 1109 * and must be free()'d by the caller. 1110 * 1111 * NOTE: This will only work if you maintain a 1112 * tree node count yourself, which you must pass 1113 * in *pulCount on input. 1114 * 1115 * This is most useful if you want to delete an 1116 * entire tree without having to traverse it 1117 * and rebalance the tree on every delete. 1118 * 1119 * Example usage for deletion: 1120 * 1121 + TREE *G_TreeRoot; 1122 + treeInit(&G_TreeRoot); 1123 + 1124 + // add stuff to the tree 1125 + TREE *pNewNode = malloc(...); 1126 + treeInsertID(&G_TreeRoot, pNewNode, FALSE) 1127 + 1128 + // now delete all nodes 1129 + ULONG cItems = ... // insert item count here 1130 + TREE** papNodes = treeBuildArray(G_TreeRoot, 1131 + &cItems); 1132 + if (papNodes) 1133 + { 1134 + ULONG ul; 1135 + for (ul = 0; ul < cItems; ul++) 1136 + { 1137 + TREE *pNodeThis = papNodes[ul]; 1138 + free(pNodeThis); 1139 + } 1140 + 1141 + free(papNodes); 1142 + } 1143 + 1144 * 1145 *@@added V0.9.9 (2001-04-05) [umoeller] 1146 */ 1147 1148 TREE** treeBuildArray(TREE* pRoot, 1149 unsigned long *pulCount) // in: item count, out: array item count 1150 { 1151 TREE **papNodes = NULL, 1152 **papThis = NULL; 1153 unsigned long cb = (sizeof(TREE*) * (*pulCount)), 1154 cNodes = 0; 1155 1156 if (cb) 1157 { 1158 papNodes = (TREE**)malloc(cb); 1159 papThis = papNodes; 1160 1161 if (papNodes) 1162 { 1163 TREE *pNode = (TREE*)treeFirst(pRoot); 1164 1165 memset(papNodes, 0, cb); 1166 1167 // copy nodes to array 1168 while ( pNode 1169 && cNodes < (*pulCount) // just to make sure 1170 ) 1171 { 1172 *papThis = pNode; 1173 cNodes++; 1174 papThis++; 1175 1176 pNode = (TREE*)treeNext(pNode); 1177 } 1178 1179 // output count 1180 *pulCount = cNodes; 1181 } 1182 } 1183 1184 return (papNodes); 1185 } 1186 1187
Note:
See TracChangeset
for help on using the changeset viewer.