/***********************
      Tip Routines
 ***********************/


/*
 *
 * Small Info Window
 * 
 *
 *
 */
int Flyer(HWND hWnd, char * Txt, HFONT font, int xp, int yp, int w)
{
	HFONT F ;
	 SIZE s ;
	POINT p ;
	  HDC d ;
	  int L ;

	p.x = xp ;
	p.y = yp ;
	ClientToScreen(hWnd, &p) ;
	xp = p.x ;
	yp = p.y ;

	p.x = rcArc.left ;
	p.y = 0 ;
	ClientToScreen(hWnd, &p) ;

	d = GetDC(hWnd) ;
	F = SelectObject(d, font) ;

	GetTextExtentPoint32(d, Txt, L = strlen(Txt), &s) ;

	// move window left by a sixteenth of the string length.

	xp -= s.cx / 16 ; 
	
	// but keep it on the screen

	while  (xp < p.x ) xp++ ;
	while ((xp + s.cx) >= p.x + horpix) xp-- ;

	// move window above its target by 3/2 character heights
	// arrange further windows, if any, above that

	yp -= 3 * s.cy / 2 + w * (s.cy + 4) ;  

// create the flyer's window
	
  hFly[w] = CreateWindow(	
		"Overlay",
		 NULL,
		 WS_POPUP | WS_BORDER,
		 xp,
		 yp,
		 s.cx,
		 s.cy,
		 hWnd,
		 NULL,
		 hInst,
	     NULL
		 );

  ShowWindow(hFly[w], SW_SHOWNA) ;	// show flyer

	SelectObject(d, F) ;
	ReleaseDC(hWnd, d) ;

	d = GetDC(hFly[w]) ;			// Supply background colour and information text
	F = SelectObject(d, font) ;
	SetBkColor(d, RGB(255, 255, 192)) ; // Pale yellow
	TextOut(d, 0, -1, Txt, L) ;  
	SelectObject(d, F) ;
	ReleaseDC(hFly[w], d) ;

	return w ;
}

/*
 * Create Overlay (Tip window)
 */
 int MakeOverlay( UINT s, int x, int y, char * String )
 {
  	   HFONT oFnt ;
         HDC hdc ;
		SIZE sz ;
		char c, * pick, * substr[30] ;

		int len, i, j, k, big, thisbig, bigline, w, h ;

		len = strlen(String) ;	   // get len of input string

		// Make room for first substring. If it can hold the
		// whole string, it can hold any substring of it. Use
		// FIXED_MEM to avoid messing about with locking.
		
		i = j = k = bigline = big = 0 ;

		substr[j] = (char *)GlobalAlloc(GPTR, len + 2) ;

		pick = substr[j++] ;
		
		while ( i <= len )			   // as long as we have some string,
		{							   // and being sure to get null char
			
			if ((c = String[i]) != 0x0a) // if char is not line feed
			{
			  pick[k++] = c ;		     // copy char to substring

			  if ( c == '\0')            // is the null at the end,
			  {						     // so this is final substring
				thisbig = strlen(pick) ; // get its size.

			    if (thisbig >= big)		 // biggest yet?
			    {
				       big = thisbig ;	 // yep, grab it
				   bigline = j - 1 ;	 // note its line
			    }
				break ;  				 // all sorted out
			  }
			  i++ ;					     // not the null. move on
			}
			else // we've hit an LF, or the end; i is now pointing at it
			{
            	pick[k] = '\0' ;         // null-terminate this substring,
				                         // overwriting the CR.
				thisbig = strlen(pick) ; // get its size

			 if (thisbig >= big)		 // biggest yet?
			 {
				    big = thisbig ;		 // yep, grab it
				bigline = j - 1 ;		 // note its line
			 }
				// make another substring
				pick = substr[j++] = (char *)GlobalAlloc(GPTR, len + 2) ;
				k = 0 ;		         // point to start of substring
				i++ ;                // move past the LF
			}
		}

// now make a top-level window and show the string(s) in it.	

 		 hdc = GetDC(hWndBud) ;	 // I suppose any window will do for this
		 oFnt = SelectObject(hdc,hfnt) ; // in with the font

		 GetTextExtentPoint32(			 // pixel sizes of longest string
			 hdc,
			 substr[bigline],
			 big,
			 &sz
			 ) ;

		 SelectObject(hdc, oFnt) ;		 // done with these
		 ReleaseDC(hWndBud,hdc) ;

		// define size of overlay window

		 w =     (int)sz.cx + 2 ;
		 h = j * (int)sz.cy + 2 ;

  		// make a pop-up window to fit the strings

  hWndInfo[s] = CreateWindow(
		"Overlay",
		 NULL,
		 WS_POPUP | WS_BORDER,
		 x,
		 y,
		 w,
		 h,
		 NULL,
		 NULL,
		 hInst,
	     NULL
		 );

	  hdc = GetDC(hWndInfo[s]) ;		  // get DC of the new window
	 oFnt = SelectObject(hdc, hfnt) ;	  // get font in
	 SetBkMode(hdc,TRANSPARENT) ;	  
	 ShowWindow(hWndInfo[s], SW_SHOWNA) ; // show but don't activate
	 
	 for ( i = 0 ; i < j ; i++)			  // print out lines
	 {
	 TextOut(hdc, 0, i * sz.cy ,substr[i], strlen(substr[i])) ;
	 GlobalFree(substr[i]) ;			  // free line's memory
	 }
	 SelectObject(hdc,oFnt) ;			  // done with these
	 ReleaseDC(hWndInfo[s], hdc) ;
	 return big ;
 }

//************************************
//        Kill a Button Tip
//************************************

void KillTip(HWND hWnd, int index) // unconditional kill
{
			    DestroyWindow(hWndInfo[index]) ;
				HaveOvly[index] = 0 ;
				     CurrentTip = (HWND)NULL ;     // no tip currently active
			   hWndOfCurrentTip = (HWND)NULL ;     // no window with active tip

			     if (Deferred[index])			   // if waiting to show, stop waiting
			     {
			      KillTimer(hWnd,IDT_TIPDEFER) ;
				  Deferred[index] = 0 ;
			     }
				 if (Dwelling[index])			   // if "waiting to hide", stop waiting
				 {
			       KillTimer(hWnd,IDT_TIPDWELL) ;
				   Dwelling[index] = 0 ;
				 }
}

void RemoveTip(void)  // should have the same effect as KillTip()
{
			    DestroyWindow(CurrentTip) ;
				HaveOvly[UseCtl] = 0 ;
				CurrentTip = (HWND)NULL ;
				hWndOfCurrentTip = (HWND)NULL ;
			     if (Deferred[UseCtl])			   // if waiting to show, stop waiting
			     {
			      KillTimer(CurrentWindow,IDT_TIPDEFER) ;
				  Deferred[UseCtl] = 0 ;
			     }
				 if (Dwelling[UseCtl])			   // if "waiting to hide", stop waiting
				 {
			       KillTimer(CurrentWindow,IDT_TIPDWELL) ;
				   Dwelling[UseCtl] = 0 ;
				 }
}

/***************************************************************
                  Put up a Button Tip
				 (Three-function suite)
 ***************************************************************/
void PutTip(HWND hWnd, int xoff, int yoff)
{
// This goes into action in reponse to a IDT_TIPDEFER timer message,
// indicating that the cursor has remained in the given control
// long enough for the corresponding tip to be shown. The cursor
// is assumed to still be in the control, so perhaps the best time
// to kill the DEFER timer is before, and to start the DWELL timer is
// after, the tip actually shows 

   POINT tpt ;

			    tpt.x = rctl[UseCtl].left ;
				tpt.y = rctl[UseCtl].bottom ;
				ClientToScreen(hWnd,&tpt) ;

				MakeOverlay((UINT)UseCtl,
				                    tpt.x + xoff,
									tpt.y + yoff,
									Tip[UseCtl] ) ;
									
			        CurrentTip = hWndInfo[UseCtl] ;
			  hWndOfCurrentTip = hWnd ;

			  onTim = SetTimer(hWnd,IDT_TIPDWELL,tDwell,NULL) ;
			  Dwelling[UseCtl] = 1 ;
}

void TryTip(HWND hWnd, int i)
{			  
					if (!HaveOvly[i])          // just arrived
					{
					HaveOvly[i] = 1 ;	       // note arrival
					UseCtl = i ;		       // say which
					                           // start DEFER show timer
					// This timer delays the
					// appearance of the tip
					// BUT
					// do not re-launch a just-clicked tip
					// while the mouse is still
					// in the control.
					if (!Clicked[i]) // the clicked state is cancelled only 
					{				 // by mouse leaving the control
					WaitTim = SetTimer(hWnd, IDT_TIPDEFER, tDefer, NULL) ;
					Deferred[i] = 1 ;
					}

                    // If the cursor
					// is still in the control
                    // when this timer fires,
                    // the tip will be shown,
					// the DEFER timer will be
					// killed, and the DWELL timer
					// will be started.
					//
					// If when the DWELL timer
					// fires the cursor is still
					// in the control, the tip will
					// be removed, and the DWELL
					// timer will be killed.
					}
				// else
				// the mouse must have MOVED in the
				// button, but it has not left it.
}

void GetTip( HWND hWnd, int first, int last, POINT cpt)
{
static	       i ;

	// This function is called when the mouse moves in a window.

	// Poll the appropriate buttons for cursor presence.
	// Put up a Tip for a cursor-occupied button.
		  for ( i = first ; i <= last ; i++)
		  {
				if (PtInRect(&rctl[i],cpt))	   // cursor is in button
				    TryTip(hWnd, i) ;		   // launch this tip
				else                           // cursor is not in button
				if (HaveOvly[i])		       // cursor just left button
				{
				    Clicked[i] = 0 ;		 // Cancel clicked state, if any,
			        KillTip(hWnd, i) ;       // and just destroy tip at once.
				}
		  }
}


void GetVoc( HWND hWnd, int first, int last, POINT cpt )
{
	int Btn ;
		// which button are we in?
			for ( Btn = first ; Btn <= last ; Btn++ )
			{
				if ((PtInRect(&rctl[Btn],cpt))==TRUE)
				{
					if (!washere[Btn]) // cursor has just entered
					{
					washere[Btn] = 1 ; // note arrival,
					UseBtn = Btn ;	         // state which button,
					                         // and start a timer.
				   // This timer delays the tip.
					VTim = SetTimer(hWnd,IDT_VOCTIMER,delay,NULL) ;
				   // If when it fires the mouse is still in the button,
				   // the tip will be played.
					}
				   // else mouse has MOVED in button (after all,
				   // this comes from WM_MOUSEMOVE ),
				   // i.e. it hasn't left the button,
				   // so DON'T restart the timer!
				}
				else // Cursor not in the button
					if (washere[Btn])        // has just left
				{
					  washere[Btn] = 0 ;     // note departure
					  KillTimer(hWnd,IDT_VOCTIMER) ; // won't need it now
				}
				// else mouse has not been in a button between calls
			}
}

