/**************************************************************************** PARAMETERS: dcache - local cache for one directory cache - pointer to variable that holds list of found families REMARKS: Extracts information from dcache and translates it to cache. This involves finding fonts with same family name and merging them into one entry in cache. Called exclusively by enumFontsInDir. {secret} ****************************************************************************/ static void buildFontEnumCache( dirCache *dcache, fontEnumCache **cache) { fontEnumCache *ecache, *tail; size_t i; fileCache *f; if (dcache->filesCnt == 0) return; qsort(dcache->files, dcache->filesCnt, sizeof(fileCache), comparFileCacheByFamily); tail = ecache = NULL; for (i = 0, f = dcache->files; i < dcache->filesCnt; i++, f++) { /* new family: */ if (tail == NULL || strcmp(tail->info.familyName, f->familyName) != 0) { if (tail == NULL) { if ((tail = ecache = PM_malloc(sizeof(fontEnumCache))) == NULL) FATALERROR(grNoMem); } else { if ((tail->next = PM_malloc(sizeof(fontEnumCache))) == NULL) FATALERROR(grNoMem); tail = tail->next; } tail->next = NULL; strcpy(tail->info.familyName, f->familyName); tail->info.fontLibType = f->fontLibType; tail->info.isFixed = f->isFixed; tail->info.regularFace[0] = '\0'; tail->info.boldFace[0] = '\0'; tail->info.italicFace[0] = '\0'; tail->info.boldItalicFace[0] = '\0'; } /* faces lookup: */ if (!f->isBold && !f->isItalic) strcpy(tail->info.regularFace, f->fileName); else if (f->isBold && !f->isItalic) strcpy(tail->info.boldFace, f->fileName); else if (!f->isBold && f->isItalic) strcpy(tail->info.italicFace, f->fileName); else if (f->isBold && f->isItalic) strcpy(tail->info.boldItalicFace, f->fileName); } tail->next = *cache; *cache = ecache; }
int main(void) { PM_HWND hwndConsole; ulong stateSize; void *stateBuf; FILE *f; /* Allocate a buffer to save console state and save the state */ hwndConsole = PM_openConsole(0,0,0,0,0,true); stateSize = PM_getConsoleStateSize(); if ((stateBuf = PM_malloc(stateSize)) == NULL) { PM_closeConsole(hwndConsole); printf("Unable to allocate console state buffer!\n"); return -1; } PM_saveConsoleState(stateBuf,0); /* Restore the console state on exit */ PM_restoreConsoleState(stateBuf,0); PM_closeConsole(hwndConsole); /* Write the saved console state buffer to disk */ if ((f = fopen("/etc/pmsave.dat","wb")) == NULL) printf("Unable to open /etc/pmsave.dat for writing!\n"); else { fwrite(&stateSize,1,sizeof(stateSize),f); fwrite(stateBuf,1,stateSize,f); fclose(f); printf("Console state successfully saved to /etc/pmsave.dat\n"); } PM_free(stateBuf); return 0; }
void * PMAPI PM_allocLockedMem( uint size, ulong *physAddr, ibool contiguous, ibool below16M) { void* linear; /* Allocate a physically contiguous buffer */ #ifdef __QNXNTO__ if ((linear = mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_PHYS|MAP_ANON,NOFD,0)) == MAP_FAILED) { #else if ((linear = mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_ANON,NOFD,0)) == -1) { #endif perror("PM_allocLockedMem mmap"); return NULL; } *physAddr = PM_getPhysicalAddr(linear); return linear; } void PMAPI PM_freeLockedMem( void *p, uint size, ibool contiguous) { if (munmap(p,size) == -1) perror("PM_freeLockedMem munmap"); } /**************************************************************************** REMARKS: Allocates a new block of pages for the page block manager. ****************************************************************************/ static pageblock *PM_addNewPageBlock(void) { int i,size; pageblock *newBlock; char *p,*next; /* Allocate memory for the new page block, and add to head of list */ size = PAGES_PER_BLOCK * PM_PAGE_SIZE + (PM_PAGE_SIZE-1) + sizeof(pageblock); if ((newBlock = PM_malloc(size)) == NULL) return NULL; newBlock->prev = NULL; newBlock->next = pageBlocks; if (pageBlocks) pageBlocks->prev = newBlock; pageBlocks = newBlock; /* Initialise the page aligned free list for the page block */ newBlock->freeCount = PAGES_PER_BLOCK; newBlock->freeList = p = (char*)(((ulong)(newBlock + 1) + (PM_PAGE_SIZE-1)) & ~(PM_PAGE_SIZE-1)); newBlock->freeListStart = newBlock->freeList; newBlock->freeListEnd = p + (PAGES_PER_BLOCK-1) * PM_PAGE_SIZE; for (i = 0; i < PAGES_PER_BLOCK; i++,p = next) FREELIST_NEXT(p) = next = p + PM_PAGE_SIZE; FREELIST_NEXT(p - PM_PAGE_SIZE) = NULL; return newBlock; }
int main(void) { int i; ulong allocs; char *p,*pa[MAXALLOC]; PM_HWND hwndConsole; hwndConsole = PM_openConsole(0,0,0,0,0,true); for (allocs = i = 0; i < MAXALLOC; i++) { if ((pa[i] = PM_malloc(10*1024)) != 0) { /* in 10k blocks */ p = pa[allocs]; memset(p, 0, 10*1024); /* touch every byte */ *p = 'x'; /* do something, anything with */ p[1023] = 'y'; /* the allocated memory */ allocs++; printf("Allocated %lu bytes\r", 10*(allocs << 10)); } else break; if (PM_kbhit() && (PM_getch() == 0x1B)) break; } PM_closeConsole(hwndConsole); printf("\n\nAllocated total of %lu bytes\n", 10 * (allocs << 10)); for (i = allocs-1; i >= 0; i--) PM_free(pa[i]); return 0; }
void * PMAPI PM_mallocShared(long size) { // TODO: This is used to allocate memory that is shared between process // that all access the common SNAP drivers via a common display // driver DLL. If your OS does not support shared memory (or if // the display driver does not need to allocate shared memory // for each process address space), this should just call PM_malloc. return PM_malloc(size); }
/**************************************************************************** REMARKS: Allocate a block of (unnamed) shared memory. ****************************************************************************/ void * PMAPI PM_mallocShared( long size) { /* TODO: This is used to allocate memory that is shared between process */ /* that all access the common Nucleus drivers via a common display */ /* driver DLL. If your OS does not support shared memory (or if */ /* the display driver does not need to allocate shared memory */ /* for each process address space), this should just call PM_malloc. */ return PM_malloc(size); }
/**************************************************************************** DESCRIPTION: Copy a portion of a device context as a lightweight memory bitmap. HEADER: mgraph.h PARAMETERS: dc - Device context to save from left - Left coordinate of bitmap to save top - Top coordinate of bitmap to save right - Right coordinate of bitmap to save bottom - Bottom coordinate of bitmap to save savePalette - Save palette with bitmap. RETURNS: Pointer to allocated bitmap, NULL on error. REMARKS: This function copies a portion of a device context as a lightweight memory bitmap. If this function fails (for instance if out of memory), it will return NULL and you can get the error code from the MGL_result function. Otherwise this function will return a pointer to a new lightweight bitmap containing the bitmap data. Note that the source rectangle for the bitmap to be saved is not clipped to the current clipping rectangle for the device context, but it is mapped to the current viewport. If you specify dimensions that are larger than the current device context, you will get garbage in the bitmap file as a result. SEE ALSO: MGL_loadBitmap, MGL_saveBitmapFromDC ****************************************************************************/ bitmap_t * MGLAPI MGL_getBitmapFromDC( MGLDC *dc, int left, int top, int right, int bottom, ibool savePalette) { bitmap_t *bitmap,bmh; long size; int palSize; /* Build the bitmap header and allocate memory for it */ createBitmapHeader(dc,&left,&top,&right,&bottom,&bmh,&palSize); if (!savePalette && (dc->mi.modeFlags & MGL_IS_COLOR_INDEX)) palSize = 0; size = sizeof(bitmap_t) + (long)bmh.bytesPerLine * bmh.height + palSize; if (dc->mi.bitsPerPixel >= 15) size += sizeof(pixel_format_t); if ((bitmap = PM_malloc(size)) == NULL) { __MGL_result = grNoMem; return NULL; } *bitmap = bmh; size = sizeof(bitmap_t); if (dc->mi.modeFlags & MGL_IS_COLOR_INDEX) { bitmap->pf = NULL; if (dc->mi.bitsPerPixel == 16) { bitmap->pf = (pixel_format_t*)((uchar*)bitmap + size); size += sizeof(pixel_format_t); *bitmap->pf = dc->pf; } if (savePalette) { bitmap->pal = (palette_t*)((uchar*)bitmap + size); size += palSize; memcpy(bitmap->pal,dc->colorTab,palSize); } else bitmap->pal = NULL; } else { bitmap->pf = (pixel_format_t*)((uchar*)bitmap + size); size += sizeof(pixel_format_t); *bitmap->pf = dc->pf; bitmap->pal = NULL; } bitmap->surface = (uchar*)bitmap + size; /* Now copy the bits from the device context into the bitmap */ MAKE_HARDWARE_CURRENT(dc,true); dc->r.GetBitmapSys(bitmap->surface,bitmap->bytesPerLine, left,top,right-left,bottom-top,0,0,GA_REPLACE_MIX); RESTORE_HARDWARE(dc,true); return bitmap; }
/**************************************************************************** DESCRIPTION: Locates an open bitmap and loads it into memory from an open file. HEADER: mgraph.h PARAMETERS: f - Open binary file to read data from dwOffset - Offset to start of bitmap in file dwSize - Size of the file loadPalette - Should we load the palette values as well? RETURNS: Pointer to the loaded bitmap file REMARKS: This function is the same as MGL_loadBitmap, however it loads the file from a previously open file. This allows you to create your own large files with multiple files embedded in them. SEE ALSO: MGL_loadBitmap, MGL_loadBitmapIntoDC ****************************************************************************/ bitmap_t * MGLAPI MGL_loadBitmapExt( FILE *f, ulong dwOffset, ulong dwSize, ibool loadPalette) { bitmap_t bmh,*bitmap; palette_t pal[256]; /* Temporary space for palette */ pixel_format_t pf; long size; int i,palSize; uchar *p; ibool isRLE; /* Open the bitmap header */ if (!readBitmapHeaderExt(&bmh,pal,&palSize,&pf,f,dwOffset,loadPalette,&isRLE)) return NULL; /* Allocate memory for the bitmap */ if (!loadPalette && bmh.bitsPerPixel <= 8) palSize = 0; size = (long)bmh.bytesPerLine * bmh.height + palSize; if ((bitmap = PM_malloc(sizeof(bitmap_t)+size)) == NULL) { FATALERROR(grNoMem); return NULL; } *bitmap = bmh; size = sizeof(bitmap_t); if (bitmap->bitsPerPixel <= 8) { if (loadPalette) { bitmap->pal = (palette_t*)((uchar*)bitmap + size); memcpy(bitmap->pal,pal,palSize); } else bitmap->pal = NULL; bitmap->pf = NULL; } else { bitmap->pf = (pixel_format_t*)((uchar*)bitmap + size); *bitmap->pf = pf; bitmap->pal = NULL; } size += palSize; bitmap->surface = (uchar*)bitmap + size; /* Now read in the bits in the bitmap. We need to handle both cases * of bottom up and top down DIB's. We can also decode RLE bitmaps * (which are always bottom up DIB format) via MGL scratch buffer. */ if (isRLE) { bufStart = (uchar*)_MGL_buf; bufSize = _MGL_bufSize; readChunk(f); gcount = gdata = 0; p = (uchar *)bitmap->surface + (long)bitmap->bytesPerLine * (bitmap->height-1); for (i = 0; i < bitmap->height; i++, p -= bitmap->bytesPerLine) { decodeScan(f,(uchar*)p,bitmap->bytesPerLine); } } else if (bitmap->height < 0) { bitmap->height = -bitmap->height; p = bitmap->surface; for (i = 0; i < bitmap->height; i++, p += bitmap->bytesPerLine) { __MGL_fread(p,1,bitmap->bytesPerLine,f); } } else { p = (uchar *)bitmap->surface + (long)bitmap->bytesPerLine * (bitmap->height-1); for (i = 0; i < bitmap->height; i++, p -= bitmap->bytesPerLine) { __MGL_fread(p,1,bitmap->bytesPerLine,f); } } (void)dwSize; return bitmap; }
/**************************************************************************** DESCRIPTION: Create a monochrome bitmap mask given a transparent color. HEADER: mgraph.h PARAMETERS: bitmap - bitmap to build monochrome mask from transparent - transparent color to mask out RETURNS: Pointer to allocated bitmap mask, or NULL on error. REMARKS: Attempts to build a monochrome bitmap mask that can be used to rasterize transparent bitmaps. This is useful for devices that have hardware BitBlt capabilities but lack hardware transparent BitBlt support. Everywhere the transparent color is found, the mask will be 0, and everywhere else it will be 1. Once you have created a monochrome bitmap mask, you can rasterize a transparent bitmap by replacing all the transparent pixels in the original bitmap with 0's, and then doing the following: 1. Set the foreground color to black and drawing the bitmap mask with MGL_putBitmapMask. Everywhere that the bitmap has data a black pixel will be used to 'punch' a hole in the display. 2. Use the MGL_bitBlt function to draw the original bitmap on the display using the MGL_OR_MODE write mode. Everywhere that a pixel is transparent in the original source bitmap, the destination will remain the same. Everywhere that a pixel is non-transparent the pixel on the destination will be replaced with the pixel in the source bitmap. Note that only 8+ bits per pixel bitmaps are supported, and this function will fail on lower color depths. SEE ALSO: MGL_transBltLin, MGL_putBitmapMask, MGL_bitBlt ****************************************************************************/ bitmap_t * MGLAPI MGL_buildMonoMask( bitmap_t *bitmap, color_t transparent) { bitmap_t *mask; int i,bytes,last; long bytesPerLine,size; uchar *ps,*ms,*m,b; __MGL_result = grOK; if (bitmap->bitsPerPixel < 8) { __MGL_result = grInvalidBitmap; return NULL; } /* Allocate memory and build bitmap header information */ bytesPerLine = (bitmap->width+7)/8; size = bytesPerLine * bitmap->height; if ((mask = PM_malloc(sizeof(bitmap_t)+size)) == NULL) { __MGL_result = grNoMem; return NULL; } mask->width = bitmap->width; mask->height = bitmap->height; mask->bitsPerPixel = 1; mask->bytesPerLine = bytesPerLine; mask->pf = NULL; mask->pal = NULL; mask->surface = (uchar*)mask + sizeof(bitmap_t); /* Now read the bits from the bitmap and build the mask */ ps = bitmap->surface; ms = mask->surface; for (i = 0; i < bitmap->height; i++, ps += bitmap->bytesPerLine, ms += bytesPerLine) { bytes = bitmap->width / 8; last = bitmap->width - (bytes * 8); m = (uchar*)ms; if (bitmap->bitsPerPixel == 8) { uchar *p = (uchar*)ps; while (bytes--) { b = 0; if (p[0] != (uchar)transparent) b |= 0x80; if (p[1] != (uchar)transparent) b |= 0x40; if (p[2] != (uchar)transparent) b |= 0x20; if (p[3] != (uchar)transparent) b |= 0x10; if (p[4] != (uchar)transparent) b |= 0x08; if (p[5] != (uchar)transparent) b |= 0x04; if (p[6] != (uchar)transparent) b |= 0x02; if (p[7] != (uchar)transparent) b |= 0x01; *m++ = b; p += 8; } if (last) { b = 0; if (last >= 1 && p[0] != (uchar)transparent) b |= 0x80; if (last >= 2 && p[1] != (uchar)transparent) b |= 0x40; if (last >= 3 && p[2] != (uchar)transparent) b |= 0x20; if (last >= 4 && p[3] != (uchar)transparent) b |= 0x10; if (last >= 5 && p[4] != (uchar)transparent) b |= 0x08; if (last >= 6 && p[5] != (uchar)transparent) b |= 0x04; if (last >= 7 && p[6] != (uchar)transparent) b |= 0x02; *m = b; } } else if (bitmap->bitsPerPixel == 15 || bitmap->bitsPerPixel == 16) { ushort *p = (ushort*)ps; while (bytes--) { b = 0; if (p[0] != (ushort)transparent) b |= 0x80; if (p[1] != (ushort)transparent) b |= 0x40; if (p[2] != (ushort)transparent) b |= 0x20; if (p[3] != (ushort)transparent) b |= 0x10; if (p[4] != (ushort)transparent) b |= 0x08; if (p[5] != (ushort)transparent) b |= 0x04; if (p[6] != (ushort)transparent) b |= 0x02; if (p[7] != (ushort)transparent) b |= 0x01; *m++ = b; p += 8; } if (last) { b = 0; if (last >= 1 && p[0] != (ushort)transparent) b |= 0x80; if (last >= 2 && p[1] != (ushort)transparent) b |= 0x40; if (last >= 3 && p[2] != (ushort)transparent) b |= 0x20; if (last >= 4 && p[3] != (ushort)transparent) b |= 0x10; if (last >= 5 && p[4] != (ushort)transparent) b |= 0x08; if (last >= 6 && p[5] != (ushort)transparent) b |= 0x04; if (last >= 7 && p[6] != (ushort)transparent) b |= 0x02; *m = b; } } else if (bitmap->bitsPerPixel == 24) { uchar *p = (uchar*)ps; uchar t0 = (uchar)transparent; uchar t1 = (uchar)(transparent >> 8); uchar t2 = (uchar)(transparent >> 16); while (bytes--) { b = 0; #define CHECK24(i) (p[(i*3)+0] != t0 || p[(i*3)+1] != t1 || p[(i*3)+2] != t2) if (CHECK24(0)) b |= 0x80; if (CHECK24(1)) b |= 0x40; if (CHECK24(2)) b |= 0x20; if (CHECK24(3)) b |= 0x10; if (CHECK24(4)) b |= 0x08; if (CHECK24(5)) b |= 0x04; if (CHECK24(6)) b |= 0x02; if (CHECK24(7)) b |= 0x01; *m++ = b; p += 24; } if (last) { b = 0; if (last >= 1 && CHECK24(0)) b |= 0x80; if (last >= 2 && CHECK24(1)) b |= 0x40; if (last >= 3 && CHECK24(2)) b |= 0x20; if (last >= 4 && CHECK24(3)) b |= 0x10; if (last >= 5 && CHECK24(4)) b |= 0x08; if (last >= 6 && CHECK24(5)) b |= 0x04; if (last >= 7 && CHECK24(6)) b |= 0x02; *m = b; } #undef CHECK24 } else {
/**************************************************************************** DESCRIPTION: Creates a new offscreen display device context. HEADER: mgraph.h PARAMETERS: dc - MGL display or windowed device context to create offscreen DC from width - Width of the offscreen device context to create height - Height of the offscreen device context to create RETURNS: Pointer to the newly created offscreen device context, NULL if not valid. REMARKS: Creates a new offscreen display device context for rendering to offscreen video memory when running in hardware accelerated video modes. You must have already created a valid display device context before this function is called, otherwise this function will return NULL. Also if the display device does not support hardware accelerated offscreen display memory, this function will also return NULL. Finally if there is no more available offscreen display memory to fullfill the request, this function will fail. See the MGL_result error code for more information if the function failed. An offscreen device context can be used just like any other MGL device context, so you can copy data around with MGL_bitBlt, or draw on the device context using any of the MGL rendering functions. If you simply want to store bitmaps in offscreen memory for fast blitting, you should instead create the bitmaps as MGL buffers with the MGL_createBuffer function. MGL buffers are similar to offscreen device contexts, except they can only be used for blitting and cannot be used as a rendering target. MGL buffers also use a lot less system memory resources than a full offscreen DC. SEE ALSO: MGL_createMemoryDC, MGL_createScrollingDisplayDC, MGL_createStereoDisplayDC, MGL_createDisplayDC, MGL_destroyDC, MGL_createBuffer ****************************************************************************/ MGLDC * MGLAPI MGL_createOffscreenDC( MGLDC *dc, int width, int height) { MGLDC *offDC; MGLBUF *buf; MGLDC *oldDC = _MGL_dcPtr; /* Create an offscreen buffer for the DC */ __MGL_result = grOK; if ((buf = MGL_createBuffer(dc,width,height,MGL_BUF_NOSYSMEM)) == NULL) { __MGL_result = grNoOffscreenMem; return NULL; } /* Now allocate memory for the device context */ if ((offDC = _LST_newNode(sizeof(MGLDC))) == NULL) { FATALERROR(grNoMem); return NULL; } if (DEV.offDCList == NULL) { if ((DEV.offDCList = _LST_create()) == NULL) { FATALERROR(grNoMem); goto Error; } } /* Clone the original DC, but allocate a new color table and reset * many of the internal variables. */ *offDC = *dc; memset(&offDC->wm,0,sizeof(offDC->wm)); offDC->v->d.refCount++; offDC->deviceType = MGL_OFFSCREEN_DEVICE; offDC->mi.xRes = buf->width-1; offDC->mi.yRes = buf->height-1; offDC->bounds.left = 0; offDC->bounds.top = 0; offDC->bounds.right = buf->width; offDC->bounds.bottom = buf->height; offDC->visRectWin = offDC->visRectWM = offDC->size = offDC->bounds; offDC->mi.maxPage = 0; offDC->mi.bytesPerLine = buf->bytesPerLine; offDC->surface = buf->surface; offDC->offBuf = buf; offDC->clipRegionUser = NULL; offDC->visRegionWM = NULL; offDC->visRegionWin = NULL; offDC->clipRegionScreen = NULL; offDC->activeBuf = TO_BUF(buf); if ((offDC->colorTab = PM_malloc(sizeof(color_t) * 256)) == NULL) { FATALERROR(grNoMem); goto Error; } /* Set the default attributes for the device context and clear it */ MGL_makeCurrentDC(offDC); MGL_defaultAttributes(offDC); MGL_setDefaultPalette(offDC); MGL_clearDevice(); MGL_makeCurrentDC(oldDC); /* Add the new DC to the start of the DC chain */ _LST_addToHead(DEV.offDCList,offDC); return offDC; Error: if (buf) MGL_destroyBuffer(buf); if (DEV.offDCList && DEV.offDCList->count == 0) { _LST_destroy(DEV.offDCList,_LST_freeNode); DEV.offDCList = NULL; } _LST_freeNode(offDC); return NULL; }
/**************************************************************************** REMARKS: Does the hard work to create the actual display device context. ****************************************************************************/ static MGLDC * _MGL_createDisplayDC( int mode, int virtualX, int virtualY, int numBuffers, ibool stereo, int refreshRate) { MGLDC *dc; driverent *entry; modeent *me = &DEV.availableModes[mode]; PM_HWND hwndConsole = (PM_HWND)NULL; /* Check if the mode is currently available */ __MGL_result = grOK; if (mode >= DEV.numModes || DEV.availableModes[mode].driver == 0xFF) { SETERROR(grInvalidMode); return NULL; } _MGL_destroyCurrentMode(); /* Allocate memory for the new DC */ if ((dc = _LST_newNode(sizeof(MGLDC))) == NULL) { FATALERROR(grNoMem); return NULL; } /* The display device list is currently empty, so create the new * list and start the specified graphics mode */ if ((DEV.dispDCList = _LST_create()) == NULL) { FATALERROR(grNoMem); goto Error; } /* Open a new fullscreen console for the mode, and save it's state */ DEV.stateBuf = NULL; if (_MGL_consoleSupport && (GET_CURRENT_DEVICE() == 0)) { hwndConsole = PM_openConsole((PM_HWND)_MGL_hwndFullScreen,GET_CURRENT_DEVICE(),me->xRes,me->yRes,me->bits,true); if ((DEV.stateBuf = PM_malloc(PM_getConsoleStateSize())) == NULL) { FATALERROR(grNoMem); goto Error; } PM_saveConsoleState(DEV.stateBuf,hwndConsole); } /* Now intialise the driver */ entry = &DEV.driverTable[me->driver]; if (!_MGL_initDC(dc,entry,me,(MGL_HWND)hwndConsole,virtualX,virtualY,numBuffers,stereo,refreshRate)) goto Error; /* Set the suspend application callback for the console */ PM_setSuspendAppCallback(_MGL_suspendAppProc); /* Set up the mouse cursor */ if (_MGL_consoleSupport) { _MS_setDisplayDC(dc); MS_setCursor(MGL_DEF_CURSOR); MS_moveTo(dc->mi.xRes/2,dc->mi.yRes/2); } /* Now clear the device page */ MGL_makeCurrentDC(dc); MGL_clearDevice(); /* And clear the event queue of any extraneous events */ if (_MGL_consoleSupport) { EVT_flush(EVT_EVERYEVT); } /* Add the new DC to the start of the DC chain */ RESET_DEFAULT_CW(); _LST_addToHead(DEV.dispDCList,dc); return dc; Error: if (hwndConsole) { if (DEV.stateBuf) { PM_restoreConsoleState(DEV.stateBuf,hwndConsole); PM_free(DEV.stateBuf); DEV.stateBuf = NULL; } PM_closeConsole(hwndConsole); } DEV.fullScreen = false; if (DEV.dispDCList && DEV.dispDCList->count == 0) { _LST_destroy(DEV.dispDCList,_LST_freeNode); DEV.dispDCList = NULL; } _LST_freeNode(dc); return NULL; }
/**************************************************************************** PARAMETERS: path - directory with font file filename - filename of the font file cache - local cache for one directory REMARKS: Updates cache entry for given font file. If such file is not in the cache, loads it with MGL_openFontLib and extracts information about font library type, family and face from it. A font is marked as bold if its name ends with " Bold", as italic if it ends with " Italic". Suffixes are cumulative. Family name is face name with recognized suffixes stripped off. For example, cache entry for font "Arial Bold Italic" will read "family is Arial, face is bold and italic". {secret} ****************************************************************************/ static void enumFontFile( const char *path, const char *filename, dirCache *cache) { char fullname[PM_MAX_PATH]; font_lib_t *fontLib; fileCache *entry; ibool isNewer; ibool foundSuffix; #if 0 // TODO: missing PM_getFileTime under Unix and DOS PM_time time; long ytimef, ytimec; #endif char *buf; size_t buflen; strcpy(fullname, path); PM_backslash(fullname); strcat(fullname, filename); /* Try to find entry in cache: */ entry = (fileCache*) bsearch(filename, cache->files, cache->filesCnt, sizeof(fileCache), searchFileCache); isNewer = (entry == NULL); #if 0 // TODO: missing PM_getFileTime under Unix and DOS if (!isNewer && PM_getFileTime(fullname, true, &time)) { ytimef = time.sec + 60 * (time.min + 60 * (time.hour + 24 * (time.day + 31 * time.mon))); ytimec = cache->timestamp.sec + 60 * (cache->timestamp.min + 60 * ( cache->timestamp.hour + 24 * (cache->timestamp.day + 31 * cache->timestamp.mon))); isNewer = time.year > cache->timestamp.year || (time.year == cache->timestamp.year && ytimef > ytimec); } #endif if (!isNewer) { cache->validCnt++; entry->exists = true; return; } /* Nothing in cache, we have to open the font: */ fontLib = MGL_openFontLib(fullname); if (fontLib == NULL) return; if (entry == NULL) { if (cache->filesCnt % CACHE_BLOCK_SIZE == 0) { cache->filesBlocks++; cache->files = PM_realloc(cache->files, sizeof(fileCache) * cache->filesBlocks * CACHE_BLOCK_SIZE); } entry = cache->files + cache->filesCnt; cache->filesCnt++; } else { PM_free(entry->fileName); PM_free(entry->familyName); } /* Try to determine family name and face type from facename: */ if ((entry->fileName = PM_malloc(strlen(filename) + 1)) == NULL) FATALERROR(grNoMem); strcpy(entry->fileName, filename); entry->fontLibType = fontLib->fontLibType; buflen = strlen(fontLib->name); if ((buf = PM_malloc(buflen + 1)) == NULL) FATALERROR(grNoMem); strcpy(buf, fontLib->name); entry->isBold = entry->isItalic = false; do { foundSuffix = false; if (buflen >= 5 && strcmp(buf + buflen - 5, " Bold") == 0) { foundSuffix = true; entry->isBold = true; buf[buflen - 5] = '\0'; buflen -= 5; } if (buflen >= 7 && strcmp(buf + buflen - 7, " Italic") == 0) { foundSuffix = true; entry->isItalic = true; buf[buflen - 7] = '\0'; buflen -= 7; } } while (buflen > 0 && foundSuffix); if (buflen == 0) { if ((entry->familyName = PM_malloc(strlen(filename) + 1)) == NULL) FATALERROR(grNoMem); strcpy(entry->familyName, filename); } else { if ((entry->familyName = PM_malloc(strlen(buf) + 1)) == NULL) FATALERROR(grNoMem); strcpy(entry->familyName, buf); } PM_free(buf); /* Check if the font is fixed width or proportional. In absence of better method, we do it by comparing average and maximum character width: */ entry->isFixed = fontIsFixed(fontLib); MGL_closeFontLib(fontLib); cache->validCnt++; entry->exists = true; }
/**************************************************************************** REMARKS: VDD implementation of the ANSI C fopen function. ****************************************************************************/ FILE * fopen( const char *filename, const char *mode) { FILE *f = PM_malloc(sizeof(FILE)); long oldpos; ULONG rc, ulAction; ULONG omode, oflags; if (f != NULL) { f->offset = 0; f->text = (mode[1] == 't' || mode[2] == 't'); f->writemode = (mode[0] == 'w') || (mode[0] == 'a'); f->unputc = EOF; f->endp = f->buf + sizeof(f->buf); f->curp = f->startp = f->buf; if (mode[0] == 'r') { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_READONLY | VDHOPEN_SHARE_DENYNONE; oflags = VDHOPEN_ACTION_OPEN_IF_EXISTS | VDHOPEN_ACTION_FAIL_IF_NEW; #else omode = OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE; oflags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; #endif } else if (mode[0] == 'w') { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_WRITEONLY | VDHOPEN_SHARE_DENYWRITE; oflags = VDHOPEN_ACTION_REPLACE_IF_EXISTS | VDHOPEN_ACTION_CREATE_IF_NEW; #else omode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE; oflags = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; #endif } else { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_READWRITE | VDHOPEN_SHARE_DENYWRITE; oflags = VDHOPEN_ACTION_OPEN_IF_EXISTS | VDHOPEN_ACTION_CREATE_IF_NEW; #else omode = OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE; oflags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; #endif } rc = _OS2Open((PSZ)filename, (PHFILE)&f->handle, &ulAction, 0, VDHOPEN_FILE_NORMAL, oflags, omode, NULL); if (rc != 0) { PM_free(f); return NULL; } #ifdef __OS2_VDD__ f->filesize = VDHSeek((HFILE)f->handle, 0, VDHSK_END_OF_FILE); #else rc = DosSetFilePtr((HFILE)f->handle, 0, FILE_END, &f->filesize); #endif if (mode[0] == 'a') fseek(f,0,2); } return f; }
void * PMAPI PM_mallocShared(long size) { return PM_malloc(size); }
static void InitPMCode(void) /**************************************************************************** * * Function: InitPMCode - 32 bit protected mode version * * Description: Finds the address of and relocates the protected mode * code block from the VBE 2.0 into a local memory block. The * memory block is allocated with malloc() and must be freed * with VBE_freePMCode() after graphics processing is complete. * * Note that this buffer _must_ be recopied after each mode set, * as the routines will change depending on the underlying * video mode. * ****************************************************************************/ { RMREGS regs; RMSREGS sregs; uchar *code; int pmLen; if (!state->pmInfo && state->VBEVersion >= 0x200) { regs.x.ax = 0x4F0A; regs.x.bx = 0; PM_int86x(0x10,®s,®s,&sregs); if (regs.x.ax != VBE_SUCCESS) return; if (VBE_shared) state->pmInfo = PM_mallocShared(regs.x.cx); else state->pmInfo = PM_malloc(regs.x.cx); if (state->pmInfo == NULL) return; state->pmInfo32 = state->pmInfo; pmLen = regs.x.cx; /* Relocate the block into our local data segment */ code = PM_mapRealPointer(sregs.es,regs.x.di); memcpy(state->pmInfo,code,pmLen); /* Now do a sanity check on the information we recieve to ensure * that is is correct. Some BIOS return totally bogus information * in here (Matrox is one)! Under DOS this works OK, but under OS/2 * we are screwed. */ if (state->pmInfo->setWindow >= pmLen || state->pmInfo->setDisplayStart >= pmLen || state->pmInfo->setPalette >= pmLen || state->pmInfo->IOPrivInfo >= pmLen) { if (VBE_shared) PM_freeShared(state->pmInfo); else PM_free(state->pmInfo); state->pmInfo32 = state->pmInfo = NULL; return; } /* Read the IO priveledge info and determine if we need to * pass a selector to MMIO registers to the bank switch code. * Since we no longer support selector allocation, we no longer * support this mechanism so we disable the protected mode * interface in this case. */ if (state->pmInfo->IOPrivInfo && !state->MMIOSel) { ushort *p = (ushort*)((uchar*)state->pmInfo + state->pmInfo->IOPrivInfo); while (*p != 0xFFFF) p++; p++; if (*p != 0xFFFF) VBE_freePMCode(); } } }
/**************************************************************************** REMARKS: VxD implementation of the ANSI C fopen function. ****************************************************************************/ FILE * fopen( const char *filename, const char *mode) { FILE *f = PM_malloc(sizeof(FILE)); long oldpos; if (f) { f->offset = 0; f->text = (mode[1] == 't' || mode[2] == 't'); f->writemode = (mode[0] == 'w') || (mode[0] == 'a'); if (initComplete) { WORD omode,error; BYTE action; if (mode[0] == 'r') { omode = OPEN_ACCESS_READONLY | OPEN_SHARE_COMPATIBLE; action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_FAIL; } else if (mode[0] == 'w') { omode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_COMPATIBLE; action = ACTION_IFEXISTS_TRUNCATE | ACTION_IFNOTEXISTS_CREATE; } else { omode = OPEN_ACCESS_READWRITE | OPEN_SHARE_COMPATIBLE; action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_CREATE; } f->handle = (int)R0_OpenCreateFile(false,(char*)filename,omode,ATTR_NORMAL,action,0,&error,&action); if (f->handle == 0) { PM_free(f); return NULL; } f->filesize = R0_GetFileSize((HANDLE)f->handle,&error); if (mode[0] == 'a') fseek(f,0,2); } else { int oflag,pmode; if (mode[0] == 'r') { pmode = _S_IREAD; oflag = _O_RDONLY; } else if (mode[0] == 'w') { pmode = _S_IWRITE; oflag = _O_WRONLY | _O_CREAT | _O_TRUNC; } else { pmode = _S_IWRITE; oflag = _O_RDWR | _O_CREAT | _O_APPEND; } if (f->text) oflag |= _O_TEXT; else oflag |= _O_BINARY; if ((f->handle = i_open(filename,oflag,pmode)) == -1) { PM_free(f); return NULL; } oldpos = i_lseek(f->handle,0,1); f->filesize = i_lseek(f->handle,0,2); i_lseek(f->handle,oldpos,0); } } return f; }
/**************************************************************************** DESCRIPTION: Returns the mask indicating what joystick axes are attached. HEADER: event.h REMARKS: This function is used to detect the attached joysticks, and determine what axes are present and functioning. This function will re-detect any attached joysticks when it is called, so if the user forgot to attach the joystick when the application started, you can call this function to re-detect any newly attached joysticks. SEE ALSO: EVT_joySetLowerRight, EVT_joySetCenter, EVT_joyIsPresent ****************************************************************************/ int EVTAPI EVT_joyIsPresent(void) { static int mask = 0; int i; char *tmp, name0[128], name1[128]; static ibool inited = false; if (inited) return mask; memset(EVT.joyMin,0,sizeof(EVT.joyMin)); memset(EVT.joyCenter,0,sizeof(EVT.joyCenter)); memset(EVT.joyMax,0,sizeof(EVT.joyMax)); memset(EVT.joyPrev,0,sizeof(EVT.joyPrev)); EVT.joyButState = 0; if ((tmp = getenv(ENV_JOYDEV0)) != NULL) strcpy(joystick0_dev,tmp); if ((tmp = getenv(ENV_JOYDEV1)) != NULL) strcpy(joystick1_dev,tmp); if ((joystick0_fd = open(joystick0_dev, O_RDONLY)) < 0) joystick0_fd = 0; if ((joystick1_fd = open(joystick1_dev, O_RDONLY)) < 0) joystick1_fd = 0; if (!joystick0_fd && !joystick1_fd) // No joysticks detected return 0; inited = true; if (ioctl(joystick0_fd ? joystick0_fd : joystick1_fd, JSIOCGVERSION, &js_version) < 0) return 0; /* Initialise joystick 0 */ if (joystick0_fd) { ioctl(joystick0_fd, JSIOCGNAME(sizeof(name0)), name0); if (js_version & ~0xffff) { struct js_event js; ioctl(joystick0_fd, JSIOCGAXES, &js0_axes); ioctl(joystick0_fd, JSIOCGBUTTONS, &js0_buttons); axis0 = PM_calloc((int)js0_axes, sizeof(short)); buts0 = PM_malloc((int)js0_buttons); /* Read the initial events */ while(dataReady(joystick0_fd) && read(joystick0_fd, &js, sizeof(struct js_event)) == sizeof(struct js_event) && (js.type & JS_EVENT_INIT) ) { if (js.type & JS_EVENT_BUTTON) buts0[js.number] = js.value; else if (js.type & JS_EVENT_AXIS) axis0[js.number] = scaleJoyAxis(js.value,js.number); } } else { js0_axes = 2; js0_buttons = 2; axis0 = PM_calloc((int)js0_axes, sizeof(short)); buts0 = PM_malloc((int)js0_buttons); } } /* Initialise joystick 1 */ if (joystick1_fd) { ioctl(joystick1_fd, JSIOCGNAME(sizeof(name1)), name1); if (js_version & ~0xffff) { struct js_event js; ioctl(joystick1_fd, JSIOCGAXES, &js1_axes); ioctl(joystick1_fd, JSIOCGBUTTONS, &js1_buttons); axis1 = PM_calloc((int)js1_axes, sizeof(short)); buts1 = PM_malloc((int)js1_buttons); /* Read the initial events */ while(dataReady(joystick1_fd) && read(joystick1_fd, &js, sizeof(struct js_event))==sizeof(struct js_event) && (js.type & JS_EVENT_INIT) ) { if (js.type & JS_EVENT_BUTTON) buts1[js.number] = js.value; else if (js.type & JS_EVENT_AXIS) axis1[js.number] = scaleJoyAxis(js.value,js.number<<2); } } else { js1_axes = 2; js1_buttons = 2; axis1 = PM_calloc((int)js1_axes, sizeof(short)); buts1 = PM_malloc((int)js1_buttons); } } #ifdef CHECKED fprintf(stderr,"Using joystick driver version %d.%d.%d\n", js_version >> 16, (js_version >> 8) & 0xff, js_version & 0xff); if (joystick0_fd) fprintf(stderr,"Joystick 1 (%s): %s\n", joystick0_dev, name0); if (joystick1_fd) fprintf(stderr,"Joystick 2 (%s): %s\n", joystick1_dev, name1); #endif mask = _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyCenter); if (mask) { for (i = 0; i < JOY_NUM_AXES; i++) EVT.joyMax[i] = EVT.joyCenter[i]*2; } return mask; }
/**************************************************************************** DESCRIPTION: Locates the specified bitmap file and loads it into a device context. HEADER: mgraph.h PARAMETERS: dc - Device context to load bitmap into f - Pointer to opened bitmap file dwSize - Size of the bitmap file dwOffset - Offset into the file dstLeft - Left coordinate to place bitmap at dstTop - Top coordinate to place bitmap at loadPalette - Should we load the palette values as well? RETURNS: True if the bitmap was successfully loaded. REMARKS: This function is the same as MGL_loadBitmapIntoDC, however it works with a previously opened file. This allows you to create your own large files with multiple files embedded in them. SEE ALSO: MGL_loadBitmapIntoDC ****************************************************************************/ ibool MGLAPI MGL_loadBitmapIntoDCExt( MGLDC *dc, FILE *f, ulong dwOffset, ulong dwSize, int dstLeft, int dstTop, ibool loadPalette) { bitmap_t bmh; palette_t pal[256]; /* Temporary space for palette */ pixel_format_t pf; int i,palSize,height; ibool oldCheckId,isRLE; /* Read bitmap header */ if (!readBitmapHeaderExt(&bmh,pal,&palSize,&pf,f,dwOffset,loadPalette,&isRLE)) return false; /* Allocate a temporary bitmap to convert the scanlines */ bmh.pal = pal; bmh.pf = &pf; if ((bmh.surface = PM_malloc(bmh.bytesPerLine)) == NULL) { FATALERROR(grNoMem); return false; } oldCheckId = MGL_checkIdentityPalette(false); /* Store the palette in the destination DC */ if (loadPalette && (bmh.bitsPerPixel == 4 || bmh.bitsPerPixel == 8)) { MGL_setPalette(dc,pal,palSize / sizeof(palette_t),0); if (MGL_getVisualPage(dc) == MGL_getActivePage(dc)) MGL_realizePalette(dc,palSize / sizeof(palette_t),0,false); } else if (loadPalette && ((dc->mi.modeFlags & MGL_IS_COLOR_INDEX) && bmh.bitsPerPixel > 8)) { MGL_getHalfTonePalette(pal); MGL_setPalette(dc,pal,MGL_getPaletteSize(dc),0); if (MGL_getVisualPage(dc) == MGL_getActivePage(dc)) MGL_realizePalette(dc,MGL_getPaletteSize(dc),0,false); } /* Now read in the bits in the bitmap, by reading the data a scanline * at a time into our temporary memory DC, and then blting this to * the destination DC. We need to handle both cases of bottom up and * top down DIB's, plus RLE decoding. */ height = bmh.height; if (isRLE) { /* Decode RLE bottom up DIB via MGL scratch buffer */ bufStart = (uchar*)_MGL_buf; bufSize = _MGL_bufSize; readChunk(f); gcount = gdata = 0; bmh.height = 1; for (i = height-1; i >= 0; i--) { decodeScan(f,bmh.surface,bmh.bytesPerLine); MGL_putBitmap(dc,dstLeft,dstTop+i,&bmh,MGL_REPLACE_MODE); } } else if (height < 0) { /* Top down DIB */ height = -bmh.height; bmh.height = 1; for (i = 0; i < height; i++) { __MGL_fread(bmh.surface,1,bmh.bytesPerLine,f); MGL_putBitmap(dc,dstLeft,dstTop+i,&bmh,MGL_REPLACE_MODE); } } else { /* Bottom up DIB */ bmh.height = 1; for (i = height-1; i >= 0; i--) { __MGL_fread(bmh.surface,1,bmh.bytesPerLine,f); MGL_putBitmap(dc,dstLeft,dstTop+i,&bmh,MGL_REPLACE_MODE); } } PM_free(bmh.surface); MGL_checkIdentityPalette(oldCheckId); (void)dwSize; return true; }
void * MGLAPI XWINDC_createInstance(void) { return PM_malloc(sizeof(XWINDC_data)); }
/**************************************************************************** PARAMETERS: dir - path to look for fntcache.inf in cache - cache structure to save loaded data to REMARKS: Initializes dirCache structure and tries to load fntcache.inf file from given directory. Silently fails if such file does not exist. fntcache.inf is text file in the following format: first line contains number of entries in decimal format, which indicates the number of file lines to follow. Each file line contains three column delimined by '\t'. Font file name is in the first column. Second column has fixed "T-F-B-I" format where T is '0', '1' or '2' (as numerical values of MGL_fontLibType are), F is 'f' for fixed size fonts and 'p' for proportional, B is 'b' for bold face and 'n' otherwise and I is 'i' for italic face and 'n' otherwise. Third column contains family name. The cache is sorted alphabetically by file name. Example file: 9 1979rg__.ttf 1-p-n-n 1979 1stgrade.ttf 1-p-n-n FirstGrader-Normal 39smooth.ttf 1-p-n-n 39 Smooth 7hours.ttf 1-p-n-n 7 hours Scot000.ttf 1-p-n-n Scott verdana.ttf 1-p-n-n Verdana verdanab.ttf 1-p-b-n Verdana verdanai.ttf 1-p-n-i Verdana verdanaz.ttf 1-p-b-i Verdana {secret} ****************************************************************************/ static void loadFontCache( const char *dir, dirCache *cache) { char filename[PM_MAX_PATH]; char buf[CACHE_LINE_SIZE]; char *c1, *c2; char bufType, bufFixed, bufBold, bufItalic; fileCache *file; FILE *f; size_t i; /* empty cache: */ cache->filesCnt = 0; cache->validCnt = 0; cache->filesBlocks = 0; cache->files = NULL; /* try to load fonts cache file from directory, silently fail if it doesn't exist: */ strcpy(filename, dir); PM_backslash(filename); strcat(filename, CACHE_FILE); f = __MGL_fopen(filename, "rt"); if (f == NULL) return; #if 0 // TODO: missing PM_getFileTime under Unix and DOS PM_getFileTime(filename, true, &cache->timestamp); #endif if (fgets(buf, CACHE_LINE_SIZE, f) == NULL) { __MGL_fclose(f); return; } /* get number of items in the cache: */ if (sscanf(buf, "%li", &cache->filesCnt) != 1 || cache->filesCnt == 0) { __MGL_fclose(f); return; } cache->filesBlocks = ((cache->filesCnt - 1) / CACHE_BLOCK_SIZE) + 1; cache->files = PM_malloc(sizeof(fileCache) * cache->filesBlocks * CACHE_BLOCK_SIZE); if (cache->files == NULL) FATALERROR(grNoMem); /* read entries. Each font file has one entry, there's one entry per line. The cache is sorted alphabetically by filename. */ for (i = 0; i < cache->filesCnt; i++) { file = cache->files + i; file->exists = false; if (fgets(buf, CACHE_LINE_SIZE, f) == NULL) { cache->filesCnt = i; __MGL_fclose(f); return; } c1 = buf; for (c2 = c1; *c2 != '\0' && *c2 != '\t'; c2++) {} *c2 = '\0'; if ((file->fileName = PM_malloc(strlen(c1) + 1)) == NULL) FATALERROR(grNoMem); strcpy(file->fileName, c1); c1 = c2 + 1; for (c2 = c1; *c2 != '\0' && *c2 != '\t'; c2++) {} *c2 = '\0'; if (sscanf(c1, "%c-%c-%c-%c", &bufType, &bufFixed, &bufBold, &bufItalic) != 4) continue; file->isBold = (bufBold == 'b'); file->isItalic = (bufItalic == 'i'); file->isFixed = (bufFixed == 'f'); file->fontLibType = bufType - '0'; c1 = c2 + 1; for (c2 = c1; *c2 != '\0'; c2++) if (*c2 == '\n' || *c2 == '\r') *c2 = '\0'; if ((file->familyName = PM_malloc(strlen(c1) + 1)) == NULL) FATALERROR(grNoMem); strcpy(file->familyName, c1); } __MGL_fclose(f); }