Esempio n. 1
0
LPOBJECT CImage::FindObject(int x, int y, BOOL fBottomUp, BOOL fExcludeBase)
{
	POINT pt;
	LPOBJECT lpObject = NULL;
	LPOBJECT lpBase;

	pt.x = x;
	pt.y = y;
	lpBase = GetBase();
	while (lpObject = GetNextObject(lpObject, fBottomUp, NO))
   	{
    	if (fExcludeBase && lpObject == lpBase)
        	continue;
    	if (AstralPtInRect(&lpObject->rObject, pt))
       	{
        	if (lpObject == lpBase)
            	return(lpObject);
        	if (!lpObject->lpAlpha)
            	return(lpObject);
        	if (IsMasked(lpObject->lpAlpha,
                    	x-lpObject->rObject.left,
                    	y-lpObject->rObject.top))
            	return(lpObject);
       	}
   	}
	return(NULL);
}
Esempio n. 2
0
FMaterialRelevance UMaterialInterface::GetRelevance_Internal(const UMaterial* Material, ERHIFeatureLevel::Type InFeatureLevel) const
{
	if(Material)
	{
		const FMaterialResource* MaterialResource = Material->GetMaterialResource(InFeatureLevel);
		const bool bIsTranslucent = IsTranslucentBlendMode((EBlendMode)GetBlendMode());

		EMaterialShadingModel ShadingModel = GetShadingModel();

		const bool bIsLit =  ShadingModel != MSM_Unlit;
		// Determine the material's view relevance.
		FMaterialRelevance MaterialRelevance;
		MaterialRelevance.bOpaque = !bIsTranslucent;
		MaterialRelevance.bMasked = IsMasked();
		MaterialRelevance.bDistortion = Material->bUsesDistortion && bIsTranslucent;
		MaterialRelevance.bSeparateTranslucency = bIsTranslucent && Material->bEnableSeparateTranslucency;
		MaterialRelevance.bNormalTranslucency = bIsTranslucent && !Material->bEnableSeparateTranslucency;
		MaterialRelevance.bDisableDepthTest = bIsTranslucent && Material->bDisableDepthTest;
		MaterialRelevance.bSubsurfaceProfile = (Material->MaterialDomain == MD_Surface) && !bIsTranslucent && (ShadingModel == MSM_SubsurfaceProfile);
		MaterialRelevance.bOutputsVelocityInBasePass = Material->bOutputVelocityOnBasePass;

		return MaterialRelevance;
	}
	else
	{
		return FMaterialRelevance();
	}
}
void FStaticMesh::AddToDrawLists(FRHICommandListImmediate& RHICmdList, FScene* Scene)
{
	const auto FeatureLevel = Scene->GetFeatureLevel();

	if (CastShadow)
	{
		FShadowDepthDrawingPolicyFactory::AddStaticMesh(Scene, this);
	}

	if (!PrimitiveSceneInfo->Proxy->ShouldRenderInMainPass())
	{
		return;
	}

	if (bUseForMaterial && Scene->RequiresHitProxies() && PrimitiveSceneInfo->Proxy->IsSelectable())
	{
		// Add the static mesh to the DPG's hit proxy draw list.
		FHitProxyDrawingPolicyFactory::AddStaticMesh(Scene, this);
	}

	if (IsTranslucent(FeatureLevel))
	{
		return;
	}

	if (Scene->ShouldUseDeferredRenderer())
	{
		if (bUseAsOccluder)
		{
			// Render non-masked materials in the depth only pass
			extern TAutoConsoleVariable<int32> CVarEarlyZPass;
			int32 EarlyZPass = CVarEarlyZPass.GetValueOnRenderThread();

			extern int32 GEarlyZPassMovable;

			// WARNING : If you change this condition, also change the logic in FStaticMeshSceneProxy::DrawStaticElements.
			if (PrimitiveSceneInfo->Proxy->ShouldUseAsOccluder() 
				&& (!IsMasked(FeatureLevel) || EarlyZPass == 2)
				&& (!PrimitiveSceneInfo->Proxy->IsMovable() || GEarlyZPassMovable))
			{
				FDepthDrawingPolicyFactory::AddStaticMesh(Scene,this);
			}
		}

		if (bUseForMaterial)
		{
			// Add the static mesh to the DPG's base pass draw list.
			FBasePassOpaqueDrawingPolicyFactory::AddStaticMesh(RHICmdList, Scene, this);
			FVelocityDrawingPolicyFactory::AddStaticMesh(Scene, this);
		}
	}
	else
	{
		if (bUseForMaterial)
		{
			// Add the static mesh to the DPG's base pass draw list.
			FBasePassForwardOpaqueDrawingPolicyFactory::AddStaticMesh(RHICmdList, Scene, this);
		}
	}
}
Esempio n. 4
0
/*
** exit_server(): Removes all dependent servers and clients, and
** sends the right messages to the right client/servers.
**
** We will send all SQUITs to &servers, and QUITs to local users.
** We only send 1 SQUIT to a 2.11 servers.
** We send all SQUITs to a 2.10 servers that can see it, or QUITs otherwise.
**
** Argument:
**	cptr: The real server to SQUIT.
**	acptr: One of the depended servers to SQUIT.
**	from: Originator of SQUIT.
**	comment: The original comment for the SQUIT. (Only for cptr itself.)
**	comment2: The comment for (S)QUIT reasons for the rest.
*/
static	void	exit_server(aClient *cptr, aClient *acptr, aClient *from,
			const char *comment, const char *comment2)
{
	aClient	*acptr2;
	int	flags;

	/* Remove all the servers recursively. */
	while (acptr->serv->down)
	{
		exit_server(cptr, acptr->serv->down, from, comment, comment2);
	}
	/* Here we should send "Received SQUIT" for last server,
	** but exit_client() is doing (well, almost) this --Beeth */

	/* This server doesn't have any depedent servers anymore, only
	** users/services left. */

	flags = FLAGS_SPLIT;

	/*
	** We'll mark all servers that can't see that server as hidden.
	** If we found any, we'll also mark all users on that server hidden.
	** If a user is marked hidden, and we try to send it to a currently
	** marked server, the server can't see that user's server.
	** Note that a 2.11 can see it, so we don't have to send the QUITs
	** to it.
	*/
	if (mark_blind_servers(cptr, acptr))
	{
		flags |= FLAGS_HIDDEN;
	}

	/* Quit all users and services. */
	while (GotDependantClient(acptr))
	{
		acptr2 = acptr->prev;
		acptr2->flags |= flags;
		exit_one_client(cptr->from, acptr2, from, comment2);
	}

	/* Make sure we only send the last SQUIT to a 2.11 server. */
	if (acptr == cptr)
	{
		acptr->flags |= FLAGS_SQUIT;
	}
	if (!IsMasked(acptr))
	{
		sendto_flag(SCH_SERVER,
			"Received SQUIT %s from %s (%s)", acptr->name,
			from->name,
			acptr == cptr ? comment : comment2);
	}
	exit_one_client(cptr->from, acptr, from,
		acptr == cptr ? comment : comment2);
	
	return;
}
Esempio n. 5
0
 uint64_t GetPayloadOffset() const {
   uint64_t r = 0;
   r += 2;
   if (UsesExtendedPayload()) {
     r += 2;
   }
   if (UsesExtendedExtendedPayloadLength()) {
     r += 8;
   }
   if (IsMasked()) {
     r += 4;
   }
   return r;
 }
Esempio n. 6
0
 uint64_t GetMessageLength() const {
   uint64_t r = GetPayloadLength();
   r += 2;
   if (UsesExtendedPayload()) {
     r += 2;
   }
   if (UsesExtendedExtendedPayloadLength()) {
     r += 8;
   }
   if (IsMasked()) {
     r += 4;
   }
   return r;
 }
Esempio n. 7
0
void FStaticMesh::AddToDrawLists(FScene* Scene)
{
	if (GRHIFeatureLevel >= ERHIFeatureLevel::SM3)
	{
		if (CastShadow)
		{
			FShadowDepthDrawingPolicyFactory::AddStaticMesh(Scene,this);
		}

		if (!bShadowOnly && PrimitiveSceneInfo->Proxy->ShouldRenderInMainPass())
		{
			// not all platforms need this
			const bool bRequiresHitProxies = Scene->RequiresHitProxies();
			if ( bRequiresHitProxies && PrimitiveSceneInfo->Proxy->IsSelectable() )
			{
				// Add the static mesh to the DPG's hit proxy draw list.
				FHitProxyDrawingPolicyFactory::AddStaticMesh(Scene,this);
			}

			if(!IsTranslucent())
			{
				extern TAutoConsoleVariable<int32> CVarEarlyZPass;
				int32 EarlyZPass = CVarEarlyZPass.GetValueOnRenderThread();

				extern int32 GEarlyZPassMovable;

				// Render non-masked materials in the depth only pass
				if (PrimitiveSceneInfo->Proxy->ShouldUseAsOccluder() 
					&& (!IsMasked() || EarlyZPass == 2)
					&& (!PrimitiveSceneInfo->Proxy->IsMovable() || GEarlyZPassMovable))
				{
					FDepthDrawingPolicyFactory::AddStaticMesh(Scene,this);
				}

				// Add the static mesh to the DPG's base pass draw list.
				FBasePassOpaqueDrawingPolicyFactory::AddStaticMesh(Scene,this);

				FVelocityDrawingPolicyFactory::AddStaticMesh(Scene, this);
			}
		}
	}
	else
	{
		if (!bShadowOnly && !IsTranslucent())
		{
			// Add the static mesh to the DPG's base pass draw list.
			FBasePassForwardOpaqueDrawingPolicyFactory::AddStaticMesh(Scene,this);
		}
	}
}
Esempio n. 8
0
 uint32_t GetMask() const {
   uint16_t* chunks = (uint16_t*)&short_header;
   chunks++;
   uint32_t r = 0;
   if (IsMasked() == false) {
     return r;
   }
   if (UsesExtendedPayload()) {
     r = (uint32_t)chunks[1] | (uint32_t)chunks[2] << 16;
   } else if (UsesExtendedExtendedPayloadLength()) {
     r = (uint32_t)chunks[4] | (uint32_t)chunks[5] << 16;
   } else {
     r = (uint32_t)chunks[0] | (uint32_t)chunks[1] << 16;
   }
   return r;
 }
Esempio n. 9
0
BOOL CImage::SelectObjects(LPOBJECT lpStartObject, LPRECT lpRect,
                BOOL fSelect, BOOL fBottomUp, BOOL fExcludeBase)
{
	BOOL        fHaveRect, fSelected;
	BOOL        fLoop;
	LPOBJECT    lpObject, lpBase;

	if (lpRect)
    	fHaveRect = lpRect->left < lpRect->right;
	fLoop = lpStartObject != NULL;
	lpObject = lpStartObject;
	fSelected = FALSE;
	lpBase = GetBase();
	while (lpObject = GetNextObject(lpObject, fBottomUp, fLoop))
    {
    	if (!fExcludeBase || lpObject != lpBase)
       	{
        	if (!lpRect)
           	{
            	if (fSelect != lpObject->fSelected)
               	{
                	ObjSelectObject((LPPRIMOBJECT)lpObject, fSelect);
                	fSelected = TRUE;
               	}
           	}
        	else if (fHaveRect)
           	{
             	if (lpObject->rObject.left >= lpRect->left &&
                	lpObject->rObject.right <= lpRect->right &&
                	lpObject->rObject.top >= lpRect->top &&
                	lpObject->rObject.bottom <= lpRect->bottom)
               	{
                	if (fSelect != lpObject->fSelected)
                   	{
                    	ObjSelectObject((LPPRIMOBJECT)lpObject, fSelect);
                    	fSelected = TRUE;
                   	}
               	}
           	}
        	else
           	{
            	if (AstralPtInRect(&lpObject->rObject, *((LPPOINT)lpRect)))
               	{
                	if (lpObject == lpBase || !lpObject->lpAlpha ||
                    	IsMasked(lpObject->lpAlpha,
                            	lpRect->left-lpObject->rObject.left,
                            	lpRect->top-lpObject->rObject.top))
                   	{
                    	if (fSelect != lpObject->fSelected)
                       	{
                        	ObjSelectObject((LPPRIMOBJECT)lpObject, fSelect);
                        	fSelected = TRUE;
                       	}
                    	break;
                   	}
               	}
           	}
       	}
    	if (lpObject == lpStartObject)
        	break;
    }
	return(fSelected);
}
Esempio n. 10
0
/*
** Exit one client, local or remote. Assuming all dependants have
** been already removed, and socket closed for local client.
*/
static	void	exit_one_client(aClient *cptr, aClient *sptr, aClient *from,
	const char *comment)
{
	Reg	aClient *acptr;
	Reg	int	i;
	Reg	Link	*lp;
	invLink		*ilp;

	/*
	**  For a server or user quitting, propagage the information to
	**  other servers (except to the one where is came from (cptr))
	*/
	if (IsMe(sptr))
	{
		sendto_flag(SCH_ERROR,
			    "ERROR: tried to exit me! : %s", comment);
		return;	/* ...must *never* exit self!! */
	}
	else if (IsServer(sptr))
	{
		/*
		** Old sendto_serv_but_one() call removed because we now
		** need to send different names to different servers
		** (domain name matching)
		*/
		if (!IsMasked(sptr))
		{
			istat.is_serv--;
		}
		if (!IsBursting(sptr))
		{
			istat.is_eobservers--;
		}
	 	for (i = fdas.highest; i >= 0; i--)
		{
			if (!(acptr = local[fdas.fd[i]]) || !IsServer(acptr) ||
			    acptr == cptr || IsMe(acptr))
			{
				continue;
			}
			if (!(sptr->flags & FLAGS_SQUIT))
			{
				/* Make sure we only send the last SQUIT
				** to a 2.11. */
				continue;
			}
			if ((acptr->flags & FLAGS_HIDDEN) &&
				!IsMasked(sptr))
			{
				/* We need a special SQUIT reason, so
				** the remote server can send the
				** right quit message. */
				sendto_one(acptr, ":%s SQUIT %s :%s %s",
					sptr->serv->up->serv->sid,
					sptr->serv->sid,
					sptr->serv->up->name,
					sptr->name);
			}
			else
			{
				sendto_one(acptr, ":%s SQUIT %s :%s",
					sptr->serv->up->serv->sid,
					sptr->serv->sid, comment);
			}
		}
#ifdef	USE_SERVICES
		check_services_butone(SERVICE_WANT_SQUIT, sptr->serv, sptr,
				      ":%s SQUIT %s :%s", from->name,
				      sptr->name, comment);
#endif
		del_from_sid_hash_table(sptr->serv);
		remove_server_from_tree(sptr);
		/* remove server from svrtop */
		unregister_server(sptr);
	}
	else if (!IsPerson(sptr) && !IsService(sptr))
	{
				    /* ...this test is *dubious*, would need
				    ** some thougth.. but for now it plugs a
				    ** nasty hole in the server... --msa
				    */
		; /* Nothing */
	}
	else if (sptr->name[0] && !IsService(sptr)) /* clean with QUIT... */
	{
		/*
		** If this exit is generated from "m_kill", then there
		** is no sense in sending the QUIT--KILL's have been
		** sent instead.
		*/
		if ((sptr->flags & FLAGS_KILLED) == 0)
		{
			if ((sptr->flags & FLAGS_SPLIT) == 0)
			{
				sendto_serv_butone(cptr, ":%s QUIT :%s",
						   sptr->user->uid, comment);
#ifdef	USE_SERVICES
				check_services_butone(SERVICE_WANT_QUIT|
						      SERVICE_WANT_RQUIT, 
						      (sptr->user) ?
						      sptr->user->servp
						      : NULL, cptr,
						      ":%s QUIT :%s",
						      sptr->name, comment);
#endif
			}
			else
			{
				if (sptr->flags & FLAGS_HIDDEN)
					/* joys of hostmasking */
					for (i = fdas.highest; i >= 0; i--)
					{
						if (!(acptr =local[fdas.fd[i]])
						    || acptr == cptr
						    || IsMe(acptr))
							continue;
						if (acptr->flags & FLAGS_HIDDEN)
							sendto_one(acptr,
								":%s QUIT :%s",
								sptr->user->uid,
								comment);
					}
#ifdef	USE_SERVICES
				check_services_butone(SERVICE_WANT_QUIT, 
					      (sptr->user) ? sptr->user->servp
						      : NULL, cptr,
						      ":%s QUIT :%s",
						      sptr->name, comment);
#endif
			}
		}
#ifdef USE_SERVICES
		else
		{
			/* Send QUIT to services which desire such as well.
			** Services with both _QUIT and _KILL will get both
			** for now --jv
			*/
			check_services_butone(SERVICE_WANT_QUIT, 
					     (sptr->user) ? sptr->user->servp
						      : NULL, cptr,
						      ":%s QUIT :%s",
						      sptr->name, comment);

		}
#endif
		/*
		** If a person is on a channel, send a QUIT notice
		** to every client (person) on the same channel (so
		** that the client can show the "**signoff" message).
		** (Note: The notice is to the local clients *only*)
		*/
		if (sptr->user)
		{
			if (IsInvisible(sptr))
			{
				istat.is_user[1]--;
				sptr->user->servp->usercnt[1]--;
			}
			else
			{
				istat.is_user[0]--;
				sptr->user->servp->usercnt[0]--;
			}
			if (IsAnOper(sptr))
			{
				sptr->user->servp->usercnt[2]--;
				istat.is_oper--;
			}
			sendto_common_channels(sptr, ":%s QUIT :%s",
						sptr->name, comment);

			if (!(acptr = cptr ? cptr : sptr->from))
				acptr = sptr;
			while ((lp = sptr->user->channel))
			{
				/*
				** Mark channels from where remote chop left,
				** this will eventually lock the channel.
				** close_connection() has already been called,
				** it makes MyConnect == False - krys
				*/
				if (sptr != cptr)
				{
					if (*lp->value.chptr->chname == '!')
					{
						if (!(sptr->flags &FLAGS_QUIT))
							lp->value.chptr->history = timeofday + LDELAYCHASETIMELIMIT;
					}
					else if (
#ifndef BETTER_CDELAY
						 !(sptr->flags & FLAGS_QUIT) &&
#endif
						 is_chan_op(sptr, lp->value.chptr))
					{
						lp->value.chptr->history = timeofday + DELAYCHASETIMELIMIT;
					}
				}
				if (IsAnonymous(lp->value.chptr) &&
				    !IsQuiet(lp->value.chptr))
				{
					sendto_channel_butserv(lp->value.chptr, sptr, ":%s PART %s :None", sptr->name, lp->value.chptr->chname);
				}
				remove_user_from_channel(sptr,lp->value.chptr);
			}

			/* Clean up invitefield */
			while ((ilp = sptr->user->invited))
			{
				del_invite(sptr, ilp->chptr);
				/* again, this is all that is needed */
			}

			/* remove from uid hash table */
			if (sptr->user)
			{
				del_from_uid_hash_table(sptr->user->uid, sptr);
			}

			/* Add user to history */
#ifndef BETTER_NDELAY
			add_history(sptr, (sptr->flags & FLAGS_QUIT) ?
				    &me : NULL);
#else
			add_history(sptr, (sptr == cptr) ? &me : NULL);
#endif
			off_history(sptr);
#ifdef USE_HOSTHASH
			del_from_hostname_hash_table(sptr->user->host,
						     sptr->user);
#endif
#ifdef USE_IPHASH
			del_from_ip_hash_table(sptr->user->sip, sptr->user);
#endif
		    }
	    }
	else if (sptr->name[0] && IsService(sptr))
	    {
		/*
		** If this exit is generated from "m_kill", then there
		** is no sense in sending the QUIT--KILL's have been
		** sent instead.
		*/
		if ((sptr->flags & FLAGS_KILLED) == 0)
		{
			/*
			** A service quitting is annoying, It has to be sent
			** to connected servers depending on 
			** sptr->service->dist
			*/
			for (i = fdas.highest; i >= 0; i--)
			    {
				if (!(acptr = local[fdas.fd[i]])
				    || !IsServer(acptr) || acptr == cptr
				    || IsMe(acptr))
				{
					continue;
				}
				if (match(sptr->service->dist, acptr->name) && 
					match(sptr->service->dist, acptr->serv->sid))
				{
					continue;
				}
				sendto_one(acptr, ":%s QUIT :%s", sptr->name,
					   comment);
			}
		}
#ifdef	USE_SERVICES
		check_services_butone(SERVICE_WANT_SERVICE, NULL, NULL,
				      ":%s QUIT :%s", sptr->name, comment);
#endif
		/* MyConnect(sptr) is always FALSE here */
		if (cptr == sptr)
		{
			sendto_flag(SCH_NOTICE, "Service %s disconnected",
				    get_client_name(sptr, TRUE));
		}
		sendto_flag(SCH_SERVICE, "Received QUIT %s from %s (%s)",
			    sptr->name, from->name, comment);
		istat.is_service--;
	    }

	/* Remove sptr from the client list */
	if (del_from_client_hash_table(sptr->name, sptr) != 1)
	{
		Debug((DEBUG_ERROR, "%#x !in tab %s[%s] %#x %#x %#x %d %d %#x",
			sptr, sptr->name,
			sptr->from ? sptr->from->sockhost : "??host",
			sptr->from, sptr->next, sptr->prev, sptr->fd,
			sptr->status, sptr->user));
	}
	remove_client_from_list(sptr);
	return;
}
Esempio n. 11
0
/*
** exit_client
**	This is old "m_bye". Name  changed, because this is not a
**	protocol function, but a general server utility function.
**
**	This function exits a client of *any* type (user, server, etc)
**	from this server. Also, this generates all necessary prototol
**	messages that this exit may cause.
**
**   1) If the client is a local client, then this implicitly
**	exits all other clients depending on this connection (e.g.
**	remote clients having 'from'-field that points to this.
**
**   2) If the client is a remote client, then only this is exited.
**
** For convenience, this function returns a suitable value for
** m_funtion return value:
**
**	FLUSH_BUFFER	if (cptr == sptr)
**	0		if (cptr != sptr)
**
**	Parameters:
**
**	aClient *cptr
** 		The local client originating the exit or NULL, if this
** 		exit is generated by this server for internal reasons.
** 		This will not get any of the generated messages.
**	aClient *sptr
**		Client exiting
**	aClient *from
**		Client firing off this Exit, never NULL!
**	char	*comment
**		Reason for the exit
*/
int	exit_client(aClient *cptr, aClient *sptr, aClient *from,
		const char *comment)
{
	char	comment1[HOSTLEN + HOSTLEN + 2];

	if (MyConnect(sptr))
	{
		if (sptr->flags & FLAGS_KILLED)
		{
			sendto_flag(SCH_NOTICE, "Killed: %s.",
				    get_client_name(sptr, TRUE));
			sptr->exitc = EXITC_KILL;
		}

		sptr->flags |= FLAGS_CLOSING;
#if (defined(FNAME_USERLOG) || defined(FNAME_CONNLOG) \
     || defined(USE_SERVICES)) \
    || (defined(USE_SYSLOG) && (defined(SYSLOG_USERS) || defined(SYSLOG_CONN)))
		if (IsPerson(sptr))
		{
# if defined(FNAME_USERLOG) || defined(USE_SERVICES) || \
	(defined(USE_SYSLOG) && defined(SYSLOG_USERS))
			sendto_flog(sptr, EXITC_REG, sptr->user->username,
				    sptr->user->host);
# endif
# if defined(CLIENTS_CHANNEL) && (CLIENTS_CHANNEL_LEVEL & CCL_QUIT)
			sendto_flag(SCH_CLIENT, "%s %s %s %s QUIT %c"
#  if (CLIENTS_CHANNEL_LEVEL & CCL_QUITINFO)
				" :%s"
#  endif
				, sptr->user->uid, sptr->name,
				sptr->user->username, sptr->user->host,
				sptr->exitc
#  if (CLIENTS_CHANNEL_LEVEL & CCL_QUITINFO)
				, comment
#  endif
				);
# endif
		}
		else if (!IsService(sptr))
		{
# if defined(FNAME_CONNLOG) || defined(USE_SERVICES) || \
	(defined(USE_SYSLOG) && defined(SYSLOG_CONN))
			if (sptr->exitc == '\0' || sptr->exitc == EXITC_REG)
			{
				sptr->exitc = EXITC_UNDEF;
			}
			sendto_flog(sptr, sptr->exitc,
				    sptr->user && sptr->user->username ?
				    sptr->user->username : "",
#ifdef UNIXPORT
				    (IsUnixSocket(sptr)) ? me.sockhost :
#endif
				    ((sptr->hostp) ? sptr->hostp->h_name :
				     sptr->sockhost));
# endif
		}
#endif
		if (MyConnect(sptr))
		{
			if (IsPerson(sptr))
			{
				istat.is_myclnt--;
			}
			else if (IsServer(sptr))
			{
				istat.is_myserv--;
			}
			else if (IsService(sptr))
			{
				istat.is_myservice--;
			}
			else
			{
				istat.is_unknown--;
			}

			if (istat.is_myclnt % CLCHNO == 0 &&
				istat.is_myclnt != istat.is_l_myclnt)
			{
				sendto_flag(SCH_NOTICE,
					"Local %screase from %d to %d clients "
					"in %d seconds",
					istat.is_myclnt>istat.is_l_myclnt?"in":"de",
					istat.is_l_myclnt, istat.is_myclnt,
					timeofday - istat.is_l_myclnt_t);
				istat.is_l_myclnt_t = timeofday;
				istat.is_l_myclnt = istat.is_myclnt;
			}
			/* Send SQUIT message to 2.11 servers to tell them
			 * the squit reason for rebroadcast on the other side
			 * - jv
			 */
			if (IsServer(sptr))
			{
				sendto_one(sptr, ":%s SQUIT %s :%s",
					me.serv->sid, sptr->serv->sid,
					comment);
			}

			if (cptr != NULL && sptr != cptr)
			{
				sendto_one(sptr, "ERROR :Closing Link: "
					"%s %s (%s)",
					get_client_name(sptr,FALSE),
					cptr->name, comment);
			}
			else
			{
				sendto_one(sptr, "ERROR :Closing Link: %s (%s)",
					get_client_name(sptr,FALSE), comment);
			}

			if (sptr->auth != sptr->username)
			{
				istat.is_authmem -= strlen(sptr->auth) + 1;
				istat.is_auth -= 1;
				MyFree(sptr->auth);
				sptr->auth = sptr->username;
			}
		}
		/*
		** Currently only server connections can have
		** depending remote clients here, but it does no
		** harm to check for all local clients. In
		** future some other clients than servers might
		** have remotes too...
		** now, I think it harms big client servers... - krys
		**
		** Close the Client connection first and mark it
		** so that no messages are attempted to send to it.
		** (The following *must* make MyConnect(sptr) == FALSE!).
		** It also makes sptr->from == NULL, thus it's unnecessary
		** to test whether "sptr != acptr" in the following loops.
		*/
		close_connection(sptr);

	} /* if (MyConnect(sptr) */

 	if (IsServer(sptr))
 	{
		/* Remove all dependent servers and clients. */
		if (!IsMasked(sptr))
		{
			sprintf(comment1, "%s %s", sptr->serv->up->name,
				sptr->name);
		}
		else
		{
			/* It was a masked server, the squit reason should
			** give the right quit reason for clients. */
			strncpyzt(comment1, comment, sizeof(comment1));
		}
		/* cptr != sptr means non-local server */
		if (cptr != sptr && 
			nextconnect == 0 && find_conf_name(sptr->name,
			(CONF_CONNECT_SERVER|CONF_ZCONNECT_SERVER)))
		{
			/* try AC */
			nextconnect = timeofday + HANGONRETRYDELAY;
		}
		exit_server(sptr, sptr, from, comment, comment1);
		check_split();
		if ((cptr == sptr))
		{
			/* It serves no purpose. --B.
			sendto_flag(SCH_SERVER, "Sending SQUIT %s (%s)",
				cptr->name, comment);
			*/
			return FLUSH_BUFFER;
		}
		return 0;
 	}
	
	/*
	** Try to guess from comment if the client is exiting
	** normally (KILL or issued QUIT), or if it is splitting
	** It requires comment for splitting users to be
	** "server.some.where splitting.some.where"
	*/
	comment1[0] = '\0';
	if ((sptr->flags & FLAGS_KILLED) == 0)
	{
		if (comment[0] == '"')
		{
			/* definitely user quit, see m_quit */
			sptr->flags |= FLAGS_QUIT;
		}
		else
		{
		        const char *c = comment;
			int i = 0;
			while (*c && *c != ' ')
				if (*c++ == '.')
					i++;
			if (*c++ && i)
			{
			        i = 0;
				while (*c && *c != ' ')
					if (*c++ == '.')
						i++;
				if (!i || *c)
					sptr->flags |= FLAGS_QUIT;
			}
			else
			{
				sptr->flags |= FLAGS_QUIT;
			}
		}

		if (sptr == cptr && !(sptr->flags & FLAGS_QUIT))
		{
			/*
			** This will avoid nick delay to be abused by
			** letting local users put a comment looking
			** like a server split.
			*/
			strncpyzt(comment1, comment, HOSTLEN + HOSTLEN);
			strcat(comment1, " ");
			sptr->flags |= FLAGS_QUIT;
		}
	}
	
	exit_one_client(cptr, sptr, from, (*comment1) ? comment1 : comment);
	/* XXX: we probably should not call it every client exit */
	/* checking every server quit should suffice --B. */
	/* check_split(); */
	return cptr == sptr ? FLUSH_BUFFER : 0;
    }