Annotation of os2sdk/demos/apps/lqh/lqhhelp.c, revision 1.1

1.1     ! root        1: /****************************************************************************
        !             2: 
        !             3:     PROGRAM: lqh.c
        !             4: 
        !             5:     MODULE: lqhhelp.c
        !             6: 
        !             7:     FUNCTIONS:
        !             8:         HelpSearch() - Retrieves a topic
        !             9:         PreLoad()    - thread for preloading topics
        !            10: 
        !            11: 
        !            12: ****************************************************************************/
        !            13: 
        !            14: #include "lqh.h"
        !            15: 
        !            16: BOOL fStructList = FALSE, fStructRequest = FALSE;
        !            17: 
        !            18: /****************************************************************************
        !            19: 
        !            20:     FUNCTION:
        !            21:         HelpSearch(NPSZ, BOOL, NC)
        !            22: 
        !            23:     PURPOSE: Retrieves a topic from the database
        !            24: 
        !            25:     COMMENTS:
        !            26:         The first parameter of HelpSearch() points to a null-terminated
        !            27:         string that contains the name of the topic to retrieve. The second
        !            28:         paramater contains a flag. When this flag is TRUE, and the topic is
        !            29:         not found, a warning box is displayed indicating that the topic was
        !            30:         not found. In other words, TRUE means display a warning, and FALSE
        !            31:         means do not. The third parameter is an optional context number. If
        !            32:         ncContext is a nonzero value, then it is used instead of the
        !            33:         pszTopic parameter.
        !            34: 
        !            35:         The return value is TRUE if the topic was found.
        !            36: 
        !            37: ****************************************************************************/
        !            38: 
        !            39: BOOL HelpSearch(npszTopic, bWarn, ncContext)
        !            40: NPSZ npszTopic;
        !            41: BOOL bWarn;
        !            42: NC ncContext;
        !            43: {
        !            44:     CHAR chBuf[256];
        !            45:     NPSZ npszTmpPtr;
        !            46:     NPCH npchBuf;
        !            47:     PCH pchPtr, pchCellString, pchTmpPtr;
        !            48:     USHORT cbLen, usLines, i;
        !            49:     SHORT cbLine;
        !            50:     SEL selDeCompress;    /* selector for current decompressed data */
        !            51:     NC ncRequest;
        !            52:     TOPICHDR FAR *tphdr;
        !            53: 
        !            54:     /* Call HelpNc to retrieve the context number of the topic requested
        !            55:      * in chBuf.
        !            56:      */
        !            57: 
        !            58:     if (!(ncRequest = ncContext))
        !            59:         if (!(ncRequest = HelpNc(npszTopic, ncHelp))) {
        !            60:             if (bWarn) {
        !            61:                 Dstrcpy(chBuf, npszTopic);
        !            62:                 Dstrcat(chBuf, " not found.");
        !            63:                 BoxMessage(chBuf, atWARNING, THIN, hmou, TRUE);
        !            64:             }
        !            65:             fStructList = fBack = FALSE;
        !            66:             return FALSE;
        !            67:         }
        !            68: 
        !            69:     pchCellString = MAKEP(selStringTable, 0);
        !            70:     if (!fBack)
        !            71:         HelpNcRecord(selTable[usCurrent].ncContext); /* Save for back-tracing */
        !            72:     else
        !            73:         fBack = fStructList = FALSE;
        !            74:     if (fStructList)
        !            75:         fStructRequest = TRUE;
        !            76:     for (i = 0; i < MAXPRELOAD; i++)
        !            77:         if (selTable[i].ncContext == ncRequest)
        !            78:             break;
        !            79: 
        !            80:     /* If a selector is found that has been preloaded, then DosLockSeg is
        !            81:      * called to prevent the segment from being discarded. If DosLockSeg
        !            82:      * returns an error, then the memory was discarded. The entry in the
        !            83:      * selector table is then cleared and new memory is allocated.
        !            84:      */
        !            85: 
        !            86:     if (i < MAXPRELOAD)
        !            87:         if (DosLockSeg(selTable[i].sel)) { /* If it can't be locked, */
        !            88:             selTable[i].ncContext = (NC) 0; /* clears entry in table */
        !            89:             selTable[i].usHighLight = 0;        /* no highlighting  */
        !            90:             DosFreeSeg(selTable[i].sel);        /* Frees the memory */
        !            91:         }
        !            92: 
        !            93:     if (i >= MAXPRELOAD || !selTable[i].ncContext) {
        !            94: 
        !            95:         /* Call HelpLook to place the compressed data into the StringTable
        !            96:          * buffer. This buffer will ultimately be used to store the
        !            97:          * character-attribute strings. HelpLook returns the amount of memory
        !            98:          * needed for the decompressed data.
        !            99:          */
        !           100: 
        !           101:         cbLen = HelpLook(ncRequest, MAKEP(selStringTable, 0));
        !           102:         if (DosAllocSeg(cbLen, &selDeCompress, SEG_DISCARDABLE)) {
        !           103:             BoxMessage(" Insufficient memory ", atWARNING,
        !           104:                 THIN, hmou, TRUE);
        !           105:             return FALSE;
        !           106:         }
        !           107: 
        !           108:         /* Convert the selector to a pointer */
        !           109: 
        !           110:         pchPtr = MAKEP(selDeCompress, 0);
        !           111: 
        !           112:         /* Decompress the data */
        !           113: 
        !           114:         HelpDecomp(pchCellString, pchPtr, ncRequest);
        !           115: 
        !           116:         if (selTable[usCurrent].sel)     /* unlock current selector */
        !           117:             DosUnlockSeg(selTable[usCurrent].sel);
        !           118: 
        !           119:         /* Find space in the table of selectors to store the current
        !           120:          * selector. Because the thread may be decompressing a file at the
        !           121:          * same time, the thread must be stopped until the usCurrent variable
        !           122:          * is set. The thread checks to make certain that it is not using the
        !           123:          * same usCurrent before writing data to the selTable strucutre.
        !           124:          */
        !           125: 
        !           126:         DosEnterCritSec();
        !           127:         usCurrent++;
        !           128:         if (usCurrent >= MAXPRELOAD)
        !           129:             usCurrent = 0;
        !           130:         DosExitCritSec();
        !           131: 
        !           132:         /* If the current selector is preloaded, free that selector
        !           133:          * before assigning a new one to it.
        !           134:          */
        !           135: 
        !           136:         if (selTable[usCurrent].sel)
        !           137:             DosFreeSeg(selTable[usCurrent].sel);
        !           138:         selTable[usCurrent].sel = selDeCompress;
        !           139:         selTable[usCurrent].usTopLine = 1;
        !           140:         selTable[usCurrent].usHighLight = 0;
        !           141:         selTable[usCurrent].ncContext = ncRequest;
        !           142:     }
        !           143:     else
        !           144:         usCurrent = i;
        !           145:     pchPtr = MAKEP(selTable[usCurrent].sel, 0);
        !           146:     tphdr = MAKEP(selTable[usCurrent].sel, 0);
        !           147: 
        !           148:     /* Databases are each allowed one special character that begins a line,
        !           149:      * and indicates it is a special line. QuickHelp specifies that lines
        !           150:      * beginning with a period are special lines and should be accepted.
        !           151:      */
        !           152: 
        !           153:     if (tphdr->appChar == '.')       /* if control char is a period */
        !           154:         tphdr->lineChar = 0xFF;      /* accept all lines            */
        !           155:     else
        !           156:         tphdr->lineChar = tphdr->appChar; /* else accept none       */
        !           157: 
        !           158:     usStructLine = usRefCount = 0;
        !           159:     fListDisplay = FALSE;
        !           160: 
        !           161:     /* It is necessary to keep two sets of line numbers. The variable
        !           162:      * usLines keeps track of the line number in the data file. This is used
        !           163:      * when requesting lines for pasting. The variable usTotalLines keeps
        !           164:      * track of the line numbers in the character-attribute string table.
        !           165:      */
        !           166: 
        !           167:     for (usLines = usTotalLines = 1;
        !           168:             (cbLine = HelpGetCells(usLines, 76,
        !           169:                 pchCellString, pchPtr, bAttr)) != -1;
        !           170:             usLines++) {
        !           171:         if (*pchCellString == '.' && cbLine) {
        !           172: 
        !           173:             /* Lines that begin with a dot are special flags for use with
        !           174:              * QuickHelp. The following flags are accepted in lqh:
        !           175:              *
        !           176:              * .category name position
        !           177:              *      Contains the category name that the current function is in,
        !           178:              *      and its position in the list of functions.
        !           179:              *
        !           180:              * .ref topics
        !           181:              *      Contains a list of space- or comma-separated topics
        !           182:              *      (functions, structures, etc.) that will appear in
        !           183:              *      the Reference menu, and that the PreLoad
        !           184:              *      thread will preload.
        !           185:              *
        !           186:              * .structure
        !           187:              *      Marks the beginning of a structure section.
        !           188:              *
        !           189:              * .list
        !           190:              *      Means that the current topic contains a list of topics.
        !           191:              *      This will cause a highlighted line to be displayed.
        !           192:              *      The user may select a topic by moving the highlighted
        !           193:              *      line over the desired topic and pressing the ENTER key.
        !           194:              *      The first word of the line is used as the topic string
        !           195:              *      to search for.
        !           196:              */
        !           197: 
        !           198:             HelpGetLine(usLines, sizeof(chBuf), chBuf, pchPtr);
        !           199:             npchBuf = chBuf + 1;
        !           200: 
        !           201:             /* .ref */
        !           202: 
        !           203:             if (chBuf[1] == 'r' && chBuf[2] == 'e' &&
        !           204:                     chBuf[3] == 'f') {
        !           205:                 npchBuf += 4;
        !           206:                 while (*npchBuf == ' ')
        !           207:                     npchBuf++;
        !           208:                 npszTmpPtr = chReference;
        !           209: MoreRef:
        !           210:                 do {
        !           211:                     npszRefTable[usRefCount++] = npszTmpPtr;
        !           212:                     while (isalpha(*npchBuf))
        !           213:                         *npszTmpPtr++ = *npchBuf++;
        !           214:                     *npszTmpPtr++ = 0;
        !           215:                     while (!isalpha(*npchBuf) && *npchBuf)
        !           216:                         npchBuf++;
        !           217:                 }
        !           218:                 while (*npchBuf && usRefCount < MAXREF);
        !           219:                 *chBuf = 0;
        !           220:                 HelpGetLine(usLines + 1, sizeof(chBuf), chBuf, pchPtr);
        !           221:                 if (strncmp(chBuf, ".ref", 4) == 0) {
        !           222:                     usLines++;
        !           223:                     npchBuf = chBuf + 5;
        !           224:                     while (*npchBuf == ' ')
        !           225:                         npchBuf++;
        !           226:                     goto MoreRef;          /* second reference line */
        !           227:                 }
        !           228:             }
        !           229: 
        !           230:             /* .list */
        !           231: 
        !           232:             else if (chBuf[1] == 'l' && chBuf[2] == 'i' &&
        !           233:                     chBuf[3] == 's' && chBuf[4] == 't') {
        !           234:                 fListDisplay = TRUE;
        !           235:                 if (chBuf[6] == 's')
        !           236:                     fStructList = TRUE;
        !           237:             }
        !           238: 
        !           239:             /* .structure */
        !           240: 
        !           241:             else if (chBuf[1] == 's' && chBuf[2] == 't' &&
        !           242:                     chBuf[3] == 'r' && chBuf[4] == 'u' &&
        !           243:                     chBuf[5] == 'c')
        !           244:                 usStructLine = usLines - 3;
        !           245:         }
        !           246:         else {
        !           247:             strTable[usTotalLines].addr = pchCellString;
        !           248:             strTable[usTotalLines++].cb = cbLine;
        !           249:             pchCellString += cbLine;
        !           250:         }
        !           251:     }
        !           252: 
        !           253:     /* Clear the semaphore to tell the thread to start preloading
        !           254:      * reference functions from the topic.
        !           255:      */
        !           256: 
        !           257:     usTotalLines--;
        !           258:     if (fListDisplay && !selTable[usCurrent].usHighLight)
        !           259:         selTable[usCurrent].usHighLight = 1;
        !           260:     if (usStructLine && fStructRequest) {
        !           261:         selTable[usCurrent].usTopLine = usStructLine;
        !           262:         fStructList = fStructRequest = FALSE;
        !           263:     }
        !           264:     DosSemClear((HSEM) &hsemNewRef);
        !           265:     return TRUE;
        !           266: }
        !           267: 
        !           268: /****************************************************************************
        !           269: 
        !           270:     THREAD: PreLoadThread
        !           271: 
        !           272:     COMMENTS:
        !           273:         In order to maximize response time, this thread preloads any
        !           274:         reference functions specified by the current function. First, it
        !           275:         waits until the hsemNewRef semaphore is cleared, which indicates
        !           276:         that a new function has been loaded. It then goes through the
        !           277:         reference table and preloads all the functions. If the hsemNewRef
        !           278:         semaphore is set before the thread completes its loop, it breaks
        !           279:         out of the loop, goes to its begining and waits for the semaphore
        !           280:         to clear.
        !           281: 
        !           282:         The thread is allowed to run only when the main process is waiting
        !           283:         for input. The Input function controls this by resuming thread
        !           284:         execution when it is called, and suspending thread execution before
        !           285:         it returns.
        !           286: 
        !           287:         This thread maintains its own pointer into the table of preloaded
        !           288:         selectors, and cycles through all selectors in a continuous loop.
        !           289: 
        !           290: ****************************************************************************/
        !           291: 
        !           292: USHORT usPreLoad = 10;                /* Maintains preload position */
        !           293: 
        !           294: VOID FAR PreLoadThread() {
        !           295:     USHORT cbLen;
        !           296:     INT i;
        !           297:     register INT j;
        !           298:     NC ncRequest;
        !           299:     SEL selDeCompress, selCompress;
        !           300: 
        !           301: Loop:
        !           302:     for (;;) {
        !           303: 
        !           304:         /* Do not begin processing until the semaphore is cleared, indicating
        !           305:          * that a new topic has been loaded.
        !           306:          */
        !           307: 
        !           308:         while (DosSemWait((HSEM) &hsemNewRef, -1L));
        !           309:         DosSemSet((HSEM) &hsemNewRef);
        !           310:         if (!usRefCount)
        !           311:             continue;
        !           312: 
        !           313:         for (i = 0; i <= usRefCount; i++) { /* Preloads all references */
        !           314:             if (i == usRefCount)
        !           315:                 ncRequest = HelpNcNext(selTable[usCurrent].ncContext);
        !           316:             else
        !           317:                 ncRequest = HelpNc(npszRefTable[i], ncHelp);
        !           318:             if (ncRequest) {
        !           319:                 for (j = 0; j < MAXPRELOAD; j++)
        !           320:                     if (selTable[j].ncContext == ncRequest)
        !           321:                         break;                 /* already preloaded */
        !           322:                 if (j >= MAXPRELOAD) {
        !           323:                     if (DosAllocSeg(HelpNcCb(ncRequest), &selCompress, 0))
        !           324:                         break;         /* Halts if allocation fails */
        !           325: 
        !           326:                     cbLen = HelpLook(ncRequest, MAKEP(selCompress, 0));
        !           327:                     if (DosAllocSeg(cbLen, (PSEL) &selDeCompress,
        !           328:                             SEG_DISCARDABLE)) {
        !           329:                         DosFreeSeg(selCompress);
        !           330:                         break;         /* Halts if allocation fails */
        !           331:                     }
        !           332:                     if (HelpDecomp(MAKEP(selCompress, 0),
        !           333:                             MAKEP(selDeCompress, 0), ncRequest)) {
        !           334:                         DosFreeSeg(selCompress);
        !           335:                         DosFreeSeg(selDeCompress);
        !           336:                         continue;
        !           337:                     }
        !           338:                     DosFreeSeg(selCompress);
        !           339:                     while (usPreLoad == usCurrent)
        !           340:                         if (++usPreLoad >= MAXPRELOAD)
        !           341:                             usPreLoad = 0;
        !           342: 
        !           343:                     /* It is crucial that the thread not change the
        !           344:                      * selTable structure at the same time that HelpSearch is
        !           345:                      * accessing it. The HelpSearch thread is suspended long
        !           346:                      * enough to confirm that the table is safe, and
        !           347:                      * is resumed only after writing to the table has
        !           348:                      * been completed. The HelpSearch function has a
        !           349:                      * similar critical section to prevent writing to the
        !           350:                      * selTable structure at the same time as the thread.
        !           351:                      */
        !           352: 
        !           353:                     DosEnterCritSec();    /* Suspends other threads */
        !           354:                     if (usPreLoad == usCurrent) {
        !           355:                         DosExitCritSec();
        !           356:                         goto Loop;
        !           357:                     }
        !           358: 
        !           359:                     if (selTable[usPreLoad].sel)
        !           360:                         DosFreeSeg(selTable[usPreLoad].sel);
        !           361:                     selTable[usPreLoad].sel = selDeCompress;
        !           362:                     selTable[usPreLoad].usTopLine = 1;
        !           363:                     selTable[usPreLoad].usHighLight = 0;
        !           364:                     selTable[usPreLoad].ncContext = ncRequest;
        !           365:                     DosUnlockSeg(selTable[usPreLoad].sel);
        !           366:                     DosExitCritSec();
        !           367:                     if (++usPreLoad >= MAXPRELOAD)
        !           368:                         usPreLoad = 0;
        !           369:                 }
        !           370: 
        !           371:                 /* If the semaphore is cleared, a new topic was loaded,
        !           372:                  * so the loop must start over again.
        !           373:                  */
        !           374: 
        !           375:                 if (!DosSemWait((HSEM) &hsemNewRef, 0L))
        !           376:                     goto Loop;
        !           377:             }
        !           378:         }
        !           379:     }
        !           380: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.