Exemplo n.º 1
0
// 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;
}
Exemplo n.º 2
0
// 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;
}