// Get backdrop pattern short display_get_pattern(BOOL use_custom) { APTR iff; BPTR file; struct WBPatternPrefs pattern[NUM_PATTERNS]; short a; char *data[NUM_PATTERNS],*filename; short change=0; ULONG flags=0; // Copy from system fields to custom fields (if custom field is empty, or custom flag is not set) for (a=0;a<4;a++) { if (!GUI->env_BackgroundPic[a][0] || !use_custom) { strcpy(GUI->env_BackgroundPic[a],environment->env->env_BackgroundPic[a]); GUI->env_BackgroundFlags[a]=environment->env->env_BackgroundFlags[a]; GUI->env_BackgroundBorderColour[a]=environment->env->env_BackgroundBorderColour[a]; } } // Pattern disabled? if (environment->env->display_options&DISPOPTF_NO_BACKDROP) { // Check both patterns are invalid for (a=0;a<NUM_PATTERNS;a++) { // Is pattern valid? if (GUI->pattern[a].valid) { // Clear existing pattern display_update_pattern(a,0); // Free pattern data FreeVec(GUI->pattern[a].data); GUI->pattern[a].data=0; // Free pattern FreePattern(&GUI->pattern[a]); } } return 0; } // Use pattern prefs? if (environment->env->display_options&DISPOPTF_USE_WBPATTERN) { // End pattern notification stop_file_notify(GUI->pattern_notify); // Get filename filename=(IntuitionBase->LibNode.lib_Version<39)?"env:sys/wb.pat":"env:sys/wbpattern.prefs"; // User-specified file? if (environment->env->backdrop_prefs[0]) { BPTR lock; // Does file exist? if (lock=Lock(environment->env->backdrop_prefs,ACCESS_READ)) { // Yep UnLock(lock); filename=environment->env->backdrop_prefs; } } // Initialise pattern and data pointers for (a=0;a<NUM_PATTERNS;a++) { pattern[a]=GUI->pattern[a].prefs; data[a]=0; } // Try to open wbpattern prefs file if (IntuitionBase->LibNode.lib_Version>=39 && (iff=IFFOpen(filename,IFF_READ,ID_PREF))) { ULONG id; // Scan for chunks we know and love while (id=IFFNextChunk(iff,0)) { // FastIPrefs FIP0 chunk? if (id==ID_FIP0) { // Get flags IFFReadChunkBytes(iff,&flags,sizeof(flags)); } // PTRN chunk? else if (id==ID_PTRN) { struct WBPatternPrefs *prefs; // Allocate space for chunk if (prefs=AllocVec(IFFChunkSize(iff),MEMF_CLEAR)) { // Read chunk IFFReadChunkBytes(iff,prefs,-1); // Pattern we can handle? if (prefs->wbp_Which==WBP_ROOT || prefs->wbp_Which==WBP_DRAWER) { // Copy data CopyMem( (char *)prefs, (char *)&pattern[prefs->wbp_Which], sizeof(struct WBPatternPrefs)); // Allocate pattern data if (prefs->wbp_DataLength>0 && (data[prefs->wbp_Which]=AllocVec(prefs->wbp_DataLength+1,MEMF_CLEAR))) { // Copy pattern data CopyMem((char *)(prefs+1),data[prefs->wbp_Which],prefs->wbp_DataLength); } } // Free chunk FreeVec(prefs); } } } // Close iff file IFFClose(iff); } // Couldn't find it, try for wb.pat else if (IntuitionBase->LibNode.lib_Version<39 && (file=Open(filename,MODE_OLDFILE))) { // Allocate pattern data if (data[PATTERN_MAIN]=AllocVec(96,MEMF_CLEAR)) { // Skip forwards Seek(file,20,OFFSET_CURRENT); // Read pattern if ((Read(file,data[PATTERN_MAIN],96))<96) { FreeVec(data[PATTERN_MAIN]); data[PATTERN_MAIN]=0; } // Fill out WBPatternPrefs else { pattern[PATTERN_MAIN].wbp_Flags=WBPF_PATTERN; pattern[PATTERN_MAIN].wbp_Depth=GUI->screen_pointer->BitMap.Depth; if (pattern[PATTERN_MAIN].wbp_Depth>MAXDEPTH) pattern[PATTERN_MAIN].wbp_Depth=MAXDEPTH; } } // Close file Close(file); } // Start notification of wbpattern prefs GUI->pattern_notify=start_file_notify(filename,NOTIFY_PATTERN_CHANGED,GUI->appmsg_port); } // Otherwise, under 39 user-defined pictures else if (GfxBase->LibNode.lib_Version>=39) { short pat; // Do both patterns for (pat=0;pat<NUM_PATTERNS;pat++) { // Got valid picture? if (GUI->env_BackgroundPic[pat][0]) { // Fill out WBPatternPrefs pattern[pat].wbp_Flags=0; pattern[pat].wbp_Which=pat; pattern[pat].wbp_DataLength=strlen(GUI->env_BackgroundPic[pat]); if (data[pat]=AllocVec(pattern[pat].wbp_DataLength+1,0)) strcpy(data[pat],GUI->env_BackgroundPic[pat]); } // Set to no pattern else { // Fill out WBPatternPrefs pattern[pat].wbp_Flags=WBPF_PATTERN; pattern[pat].wbp_DataLength=0; data[pat]=0; } } } // Otherwise, default to no pattern else { short pat; // Do both patterns for (pat=0;pat<NUM_PATTERNS;pat++) { // Fill out WBPatternPrefs pattern[pat].wbp_Flags=WBPF_PATTERN; pattern[pat].wbp_DataLength=0; data[pat]=0; } } // Go through both patterns for (a=0;a<NUM_PATTERNS;a++) { BOOL diff=0; short precision=0; // Using Opus settings? if (!(environment->env->display_options&DISPOPTF_USE_WBPATTERN)) { // Get precision if (GUI->env_BackgroundFlags[a]&ENVBF_PRECISION_NONE) precision=-1; else if (GUI->env_BackgroundFlags[a]&ENVBF_PRECISION_GUI) precision=2; else if (GUI->env_BackgroundFlags[a]&ENVBF_PRECISION_ICON) precision=1; else if (GUI->env_BackgroundFlags[a]&ENVBF_PRECISION_EXACT) precision=3; } // Maybe set in prefs else { // Get precision precision=(a==0)?PATF_WB_MODE(flags):PATF_LISTER_MODE(flags); } // Valid data? if (data[a]) { // No last pattern? if (!GUI->pattern[a].data) { diff=1; } // Changed from pattern to picture or vice versa? else if ((pattern[a].wbp_Flags&WBPF_PATTERN && !(GUI->pattern[a].prefs.wbp_Flags&WBPF_PATTERN)) || (!(pattern[a].wbp_Flags&WBPF_PATTERN) && GUI->pattern[a].prefs.wbp_Flags&WBPF_PATTERN)) { diff=1; } // Pattern pattern? else if (pattern[a].wbp_Flags&WBPF_PATTERN) { // Different depth? if (pattern[a].wbp_Depth!=GUI->pattern[a].prefs.wbp_Depth) diff=1; // Has data changed from the last one? else { short num,d; // Get amount of data num=PAT_HEIGHT*pattern[a].wbp_Depth; // Compare data for (d=0;d<num;d++) { if (((USHORT *)data[a])[d]!=((USHORT *)GUI->pattern[a].data)[d]) { diff=1; break; } } } } // Picture? else { // Different name for picture, or it's random? if (strcmp(data[a],GUI->pattern[a].data)!=0 || GUI->pattern[a].random) { diff=1; } // Precision changed? else if (precision!=GUI->pattern[a].precision) { diff=1; } // Stretching changed? else if (a==0 && ((GUI->env_BackgroundFlags[a]&ENVBF_STRETCH_PIC && !(GUI->pattern[a].flags&PATF_STRETCH)) || !(GUI->env_BackgroundFlags[a]&ENVBF_STRETCH_PIC) && (GUI->pattern[a].flags&PATF_STRETCH))) { diff=1; } // Centering changed? else if ((GUI->env_BackgroundFlags[a]&ENVBF_CENTER_PIC && !(GUI->pattern[a].flags&PATF_CENTER)) || !(GUI->env_BackgroundFlags[a]&ENVBF_CENTER_PIC) && (GUI->pattern[a].flags&PATF_CENTER)) { diff=2; } } } // Had last data? else if (GUI->pattern[a].data) diff=1; if (diff!=1) { // Border pen changed? if ((GUI->env_BackgroundFlags[a]&ENVBF_USE_COLOUR && GUI->pattern[a].border_pen==0) || (!(GUI->env_BackgroundFlags[a]&ENVBF_USE_COLOUR) && GUI->pattern[a].border_pen!=0)) { diff=3; } else if (GUI->pattern[a].border_pen!=0 && GUI->env_BackgroundFlags[a]&ENVBF_USE_COLOUR) { ULONG col[3]; GetPalette32( &GUI->screen_pointer->ViewPort, col, 1, (GUI->pattern[a].border_pen==-1)?0:GUI->pattern[a].border_pen); if (ENVBF_COL_R_GET(col[0])!=ENVBF_COL_R_GET(GUI->env_BackgroundBorderColour[a]) || ENVBF_COL_R_GET(col[1])!=ENVBF_COL_G_GET(GUI->env_BackgroundBorderColour[a]) || ENVBF_COL_R_GET(col[2])!=ENVBF_COL_B_GET(GUI->env_BackgroundBorderColour[a])) { diff=3; } } } // Has it changed? if (diff) { // Existing pattern valid? if (GUI->pattern[a].valid) { // Clear existing patterns display_update_pattern(a,0); } // Change more than centering? if (diff==1) { // Free existing pattern FreePattern(&GUI->pattern[a]); FreeVec(GUI->pattern[a].data); // Copy pattern and data pointer GUI->pattern[a].prefs=pattern[a]; GUI->pattern[a].data=data[a]; // Stretch? if (a==0 && GUI->env_BackgroundFlags[a]&ENVBF_STRETCH_PIC) { flags|=PATF_STRETCH; flags&=~PATF_CENTER; } else { flags&=~PATF_STRETCH; if (!(environment->env->display_options&DISPOPTF_USE_WBPATTERN) && GUI->env_BackgroundFlags[a]&ENVBF_CENTER_PIC) flags|=PATF_CENTER; else flags&=~PATF_CENTER; } // Set flags and precision GUI->pattern[a].flags=flags; GUI->pattern[a].precision=precision; // Initialise pattern GetPattern( &GUI->pattern[a], GUI->screen_pointer, GUI->env_BackgroundBorderColour[a]|(GUI->env_BackgroundFlags[a]&ENVBF_USE_COLOUR)); } // Change colour else if (diff==3) { // Initialise pattern colour GetPatternBorder( &GUI->pattern[a], GUI->screen_pointer, GUI->env_BackgroundBorderColour[a]|(GUI->env_BackgroundFlags[a]&ENVBF_USE_COLOUR)); } // Centering changed else { // Environment flags set for centering? if (!(environment->env->display_options&DISPOPTF_USE_WBPATTERN) && GUI->env_BackgroundFlags[a]&ENVBF_CENTER_PIC) GUI->pattern[a].flags|=PATF_CENTER; else GUI->pattern[a].flags&=~PATF_CENTER; } // Install new pattern display_update_pattern(a,1); } // If not, free data else FreeVec(data[a]); } return change; }
// Load a backfill pattern; pattern must be locked exclusively void GetPattern(PatternData *pattern,struct Screen *screen,ULONG border_col) { // Initially make invalid pattern->valid=FALSE; pattern->border_pen=0; // Set screen pointer pattern->screen=screen; // Check for invalid data if (!pattern->data) { // Update border pen GetPatternBorder(pattern,screen,border_col); return; } // Bitmap pattern? if (pattern->prefs.wbp_Flags&WBPF_PATTERN) { UWORD *ptr,*planes[MAXDEPTH]; short num,row,col,pen; // Get plane pointers for (num=0;num<pattern->prefs.wbp_Depth;num++) { planes[num]=((UWORD *)pattern->data)+(PAT_HEIGHT*num); } pattern->fill_plane_key=0; // Clear fill initially for (num=0,ptr=pattern->fill[0];num<128;num++,ptr++) *ptr=0; // Under 37 use fill pattern as supplied if (((struct Library *)GfxBase)->lib_Version<39) { for (num=0;num<pattern->prefs.wbp_Depth;num++) { CopyMem( (char *)planes[num], (char *)pattern->fill[num], PAT_HEIGHT*sizeof(UWORD)); } pattern->fill_plane_key=pattern->prefs.wbp_Depth; } // Otherwise, we need to remap else { // Go through pattern rows for (row=0;row<PAT_HEIGHT;row++) { // Go through bits for (col=0;col<PAT_WIDTH;col++) { // Clear pen pen=0; // Calculate pixel colour for (num=0;num<pattern->prefs.wbp_Depth;num++) { // Is bit set in this bitplane? if (planes[num][row]&(1<<col)) pen|=(1<<num); } // Pixel set? if (pen) { // Map pens 4-7 to top four colours if (pen>=4 && screen->RastPort.BitMap->Depth<=8) { pen=(1<<screen->RastPort.BitMap->Depth)-(8-pen); } // Remap for (num=0;num<8;num++) { // Want this bit? if (pen&(1<<num)) { // Set bit pattern->fill[num][row]|=1<<col; if (num>=pattern->fill_plane_key) pattern->fill_plane_key=num+1; } } } } } } // Any data? if (pattern->fill_plane_key>0) { short depth; // Get depth for bitmap if (((struct Library *)GfxBase)->lib_Version>=39) depth=GetBitMapAttr(screen->RastPort.BitMap,BMA_DEPTH); else depth=screen->RastPort.BitMap->Depth; // Check its not too deep if (depth>8) depth=8; // Allocate bitmap for pattern if ((pattern->pattern_bitmap= NewBitMap( PATTILE_SIZE, PATTILE_SIZE, depth, BMF_CLEAR, 0))) { struct RastPort rp; struct BitMap *bitmap; // Initialise dummy rastport InitRastPort(&rp); rp.BitMap=pattern->pattern_bitmap; // Set fill pattern SetAfPt(&rp,pattern->fill[0],-4); // Fill bitmap SetRast(&rp,0); RectFill(&rp,0,0,PATTILE_SIZE-1,PATTILE_SIZE-1); // Is the screen a non-standard bitmap? if (((struct Library *)GfxBase)->lib_Version>=39 && !(GetBitMapAttr(screen->RastPort.BitMap,BMA_FLAGS)&BMF_STANDARD)) { // Try and allocate friend bitmap if ((bitmap= NewBitMap( PATTILE_SIZE, PATTILE_SIZE, depth, BMF_CLEAR, screen->RastPort.BitMap))) { // Copy to friend bitmap BltBitMap( pattern->pattern_bitmap,0,0, bitmap,0,0, PATTILE_SIZE,PATTILE_SIZE, 0xc0,0xff,0); // Free original bitmap DisposeBitMap(pattern->pattern_bitmap); // Use new bitmap pointer pattern->pattern_bitmap=bitmap; } } // Get bitmap pointer pattern->bitmap=pattern->pattern_bitmap; // Get pattern size pattern->width=PATTILE_SIZE; pattern->height=PATTILE_SIZE; } } } // Picture; must have datatypes else if (DataTypesBase) { short len; BOOL remap=1; long precision=PRECISION_IMAGE; char name[256]; long ver=0; struct Library *pdt; #ifdef PATCH_OK APTR patchhandle=0; #endif // Check picture datatype version if ((pdt=OpenLibrary("sys:classes/datatypes/picture.datatype",0)) || (pdt=OpenLibrary("picture.datatype",0))) { // Get version ver=pdt->lib_Version; CloseLibrary(pdt); } // No remap? if ((len=strlen(pattern->data))>8 && stricmp(pattern->data+len-8,".noremap")==0) remap=0; // Precision? if (len>6 && stricmp(pattern->data+len-6,".exact")==0) precision=PRECISION_EXACT; // Specified in prefs? else if (pattern->precision) { if (pattern->precision==-1) remap=0; else if (pattern->precision==1) precision=PRECISION_ICON; else if (pattern->precision==2) precision=PRECISION_GUI; else if (pattern->precision==3) precision=PRECISION_EXACT; } #ifdef PATCH_OK // If we've got v43 of the datatype, we don't need the fastram patch if (ver<43) { // Add this task to the patchlist for allocbitmap patchhandle=AddAllocBitmapPatch(FindTask(0),screen); } #endif // Turn back on requesters ((struct Process *)FindTask(0))->pr_WindowPtr=GUI->window; // Check for random pictures, and then load picture if (pattern_check_random(pattern,name) && (pattern->object= NewDTObject(name, DTA_GroupID,GID_PICTURE, PDTA_Screen,screen, PDTA_FreeSourceBitMap,TRUE, (ver>42)?PDTA_DestMode:TAG_IGNORE,MODE_V43, (ver>42)?PDTA_UseFriendBitMap:TAG_IGNORE,TRUE, TAG_END))) { struct BitMapHeader *header; struct BitMap *bitmap; D_S(struct FileInfoBlock, fib) // Get file information if (GetFileInfo(name,fib) && strnicmp(fib->fib_Comment,"dopus ",6)==0) { char *args=fib->fib_Comment+6; short val; rexx_skip_space(&args); while ((val=rexx_match_keyword(&args,background_key,0))!=-1) { // Tile/center/stretch if (val==3) pattern->flags&=~(PATF_CENTER|PATF_STRETCH); else if (val==4) { pattern->flags|=PATF_CENTER; pattern->flags&=~PATF_STRETCH; } else if (val==5 && pattern->prefs.wbp_Which==0) { pattern->flags|=PATF_STRETCH; pattern->flags&=~PATF_CENTER; } // Precision else if (val==6) { // Get precision rexx_skip_space(&args); if ((val=rexx_match_keyword(&args,precision_key,0))>-1) { if (val==0) remap=0; else if (val==1) precision=PRECISION_GUI; else if (val==2) precision=PRECISION_ICON; else if (val==3) precision=PRECISION_IMAGE; else if (val==4) precision=PRECISION_EXACT; } } // Border else if (val==8) { // Off? rexx_skip_space(&args); if (rexx_match_keyword(&args,on_off_strings2,0)==0) border_col&=~ENVBF_USE_COLOUR; else { border_col=ENVBF_USE_COLOUR; border_col|=Atoh(args,-1)<<8; } } } } // Layout picture (should check for success) SetDTAttrs(pattern->object,0,0, OBP_Precision,precision, PDTA_Remap,remap, TAG_END); DoMethod(pattern->object,DTM_PROCLAYOUT,0,1); // Get bitmap pointer and header GetDTAttrs(pattern->object, PDTA_BitMap,&bitmap, PDTA_DestBitMap,&pattern->bitmap, PDTA_BitMapHeader,&header, TAG_END); // No dest bitmap? if (!pattern->bitmap) pattern->bitmap=bitmap; // Valid bitmap? if (pattern->bitmap) { // Get width and height pattern->width=header->bmh_Width; pattern->height=header->bmh_Height; } } // Turn off requesters ((struct Process *)FindTask(0))->pr_WindowPtr=(APTR)-1; #ifdef PATCH_OK // Remove this task from the patchlist for allocbitmap if (patchhandle) RemAllocBitmapPatch(patchhandle); #endif // Got bitmap? if (pattern->bitmap) { // Stretch? if (pattern->flags&PATF_STRETCH) { // Not the size of the screen? if (pattern->width!=screen->Width || pattern->height!=screen->Height) { // Allocate a bitmap for the stretched picture if ((pattern->pattern_bitmap= NewBitMap( screen->Width, screen->Height, GetBitMapAttr(pattern->bitmap,BMA_DEPTH), BMF_CLEAR, screen->RastPort.BitMap))) { struct BitScaleArgs scale; // Scale bitmap scale.bsa_SrcX=0; scale.bsa_SrcY=0; scale.bsa_SrcWidth=pattern->width; scale.bsa_SrcHeight=pattern->height; scale.bsa_DestX=0; scale.bsa_DestY=0; scale.bsa_DestWidth=screen->Width; scale.bsa_DestHeight=screen->Height; scale.bsa_XSrcFactor=scale.bsa_SrcWidth; scale.bsa_XDestFactor=scale.bsa_DestWidth; scale.bsa_YSrcFactor=scale.bsa_SrcHeight; scale.bsa_YDestFactor=scale.bsa_DestHeight; scale.bsa_SrcBitMap=pattern->bitmap; scale.bsa_DestBitMap=pattern->pattern_bitmap; scale.bsa_Flags=0; BitMapScale(&scale); // Get pointer to scaled bitmap pattern->bitmap=pattern->pattern_bitmap; pattern->width=screen->Width; pattern->height=screen->Height; } } } } // Update border pen GetPatternBorder(pattern,screen,border_col); } // Pattern ok now pattern->valid=TRUE; }