Thread: Abnormal termination

  1. #1
    Registered User
    Join Date
    Aug 2011
    Posts
    385

    Abnormal termination

    Can someone please debug this code. I have tried everything and made sure that everything is fine, but still the program terminates when I try to resize the window. I believe the problem is with line no. 120. Commenting it out solves the problem, but I can't figure out what's wrong.
    The program is rudimentary and still under devopement. It is a simple and very basic text editor with no advanced functionality. In WM_SIZE I am trying to allocate additional space when the window size is increased and fill this newly allocated space with blanks.
    I would really appreciate any help.. Thanks in advance...



    Code:
    #include <windows.h>
    
    #define BUFFER(x,y) *(pBuffer + y * cxBuffer + x)
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
         static TCHAR szAppName[] = TEXT ("Typer") ;
         HWND         hwnd ;
         MSG          msg ;
         WNDCLASS     wndclass ;
         
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = WndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = 0 ;
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szAppName ;
    
         if (!RegisterClass (&wndclass))
         {
              MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
                          szAppName, MB_ICONERROR) ;
              return 0 ;
         }
         
         hwnd = CreateWindow (szAppName, TEXT ("Typing Program"),
                              WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              NULL, NULL, hInstance, NULL) ;
         
    	 if(hwnd == NULL)MessageBox(NULL, TEXT("Allocation failed"), NULL, MB_ICONERROR);
         ShowWindow (hwnd, iCmdShow) ;
         UpdateWindow (hwnd) ;
         
         while (GetMessage (&msg, NULL, 0, 0))
         {
              TranslateMessage (&msg) ;
              DispatchMessage (&msg) ;
         }
         return msg.wParam ;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
         static DWORD   dwCharSet = DEFAULT_CHARSET ;
         static int     cxChar, cyChar, cxClient, cyClient, cxBuffer, cyBuffer,
                        xCaret, yCaret,xprev,yprev ;
         static TCHAR * pBuffer = NULL, *pOldBuff,*pNewBuff,s[200] ;
         HDC            hdc ;
         static long            x, y, i ;
         PAINTSTRUCT    ps ;
         TEXTMETRIC     tm ;
         RECT rect;
    
         switch (message)
         {
         case WM_INPUTLANGCHANGE:
              dwCharSet = wParam ;
                                            // fall through
         case WM_CREATE:
              hdc = GetDC (hwnd) ;
              SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,
                                       dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;
              
              GetTextMetrics (hdc, &tm) ;
              cxChar = tm.tmAveCharWidth ;
              cyChar = tm.tmHeight ;
              
              DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
              ReleaseDC (hwnd, hdc) ;
    		 
    		  GetClientRect(hwnd,&rect);
    		  cxClient = rect.right;
    		  cyClient = rect.bottom;
    		  cxBuffer = max(1, cxClient/cxChar);
    		  cyBuffer = max(1, cyClient/cyChar);
    		  pBuffer = (TCHAR *) malloc (cxBuffer * cyBuffer * sizeof (TCHAR)) ;
    		  
    		  if(pBuffer == NULL)
    		  {
    			MessageBox(NULL, TEXT("Allocation failed"), NULL, MB_ICONERROR);
    			return 0;
    		  }
    
    		  for (y = 0 ; y < cyBuffer ; y++)
                   for (x = 0 ; x < cxBuffer ; x++)
                        BUFFER(x,y) = ' ' ;
    
         case WM_SIZE:
    			if(message == WM_SIZE)
    			{
    			  xprev = cxBuffer; yprev = cyBuffer;
    				
    			  x = &BUFFER(xprev,yprev) - &BUFFER(0,0) ;
    				
    			  								
                  cxClient = LOWORD (lParam) ;
                  cyClient = HIWORD (lParam) ;
    			
              
              	  cxBuffer = max (1, cxClient / cxChar) ;
              	  cyBuffer = max (1, cyClient / cyChar) ;
    			
              
    
    			
       		      pBuffer = (TCHAR *) realloc (pBuffer,cxBuffer * cyBuffer * sizeof (TCHAR));
    
    			  pOldBuff = &BUFFER(0,0) + x ;
    			  pNewBuff = &BUFFER(cxBuffer,cyBuffer);
    	
        	      y = pNewBuff - (&BUFFER(0,0));
    			   
    			  if(y>x)  
    				for( ; pNewBuff != (pOldBuff) ; pNewBuff--)
    						*(pNewBuff) = ' ';
                 
                }
              
                        
                       
              if (hwnd == GetFocus ())
                   SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;
    
              InvalidateRect (hwnd, NULL, FALSE) ;
              return 0 ;
                        
         case WM_SETFOCUS:
                   // create and show the caret
    
              CreateCaret (hwnd, NULL, cxChar, cyChar) ;
              SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;
              ShowCaret (hwnd) ;
              return 0 ;
              
         case WM_KILLFOCUS:
                   // hide and destroy the caret
    
              HideCaret (hwnd) ;
              DestroyCaret () ;
              return 0 ;
              
         case WM_KEYDOWN:
              switch (wParam)
              {
              case VK_HOME:
                   xCaret = 0 ;
                   break ;
                   
              case VK_END:
                   xCaret = cxBuffer - 1 ;
                   break ;
                   
              case VK_PRIOR:
                   yCaret = 0 ;
                   break ;
                   
              case VK_NEXT:
                   yCaret = cyBuffer - 1 ;
                   break ;
                   
              case VK_LEFT:
                   xCaret = max (xCaret - 1, 0) ;
                   break ;
                   
              case VK_RIGHT:
                   xCaret = min (xCaret + 1, cxBuffer - 1) ;
                   break ;
                   
              case VK_UP:
                   yCaret = max (yCaret - 1, 0) ;
                   break ;
                   
              case VK_DOWN:
                   yCaret = min (yCaret + 1, cyBuffer - 1) ;
                   break ;
                   
              case VK_DELETE:
                   for (x = xCaret ; x < cxBuffer - 1 ; x++)
                        BUFFER (x, yCaret) = BUFFER (x + 1, yCaret) ;
                   
                   BUFFER (cxBuffer - 1, yCaret) = ' ' ;
                   
                   HideCaret (hwnd) ;
                   hdc = GetDC (hwnd) ;
              
                   SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,
                                       dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;
                        
                   TextOut (hdc, xCaret * cxChar, yCaret * cyChar,
                            & BUFFER (xCaret, yCaret),
                            cxBuffer - xCaret) ;
    
                   DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
                   ReleaseDC (hwnd, hdc) ;
                   ShowCaret (hwnd) ;
                   break ;
              }
              SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;
              return 0 ;
              
         case WM_CHAR:
              for (i = 0 ; i < (int) LOWORD (lParam) ; i++)
              {
                   switch (wParam)
                   {
                   case '\b':                    // backspace
                        if (xCaret > 0)
                        {
                             xCaret-- ;
                             SendMessage (hwnd, WM_KEYDOWN, VK_DELETE, 1) ;
                        }
                        break ;
                        
                   case '\t':                    // tab
                        do
                        {
                             SendMessage (hwnd, WM_CHAR, ' ', 1) ;
                        }
                        while (xCaret % 8 != 0) ;
                        break ;
    
                  case '\n':                    // line feed
                        if (++yCaret == cyBuffer)
                             yCaret = 0 ;
                        break ;
                        
                   case '\r':                    // carriage return
                        xCaret = 0 ;
                        
                        if (++yCaret == cyBuffer)
                             yCaret = 0 ;
                        break ;
                        
                   case '\x1B':                  // escape
                        for (y = 0 ; y < cyBuffer ; y++)
                             for (x = 0 ; x < cxBuffer ; x++)
                                  BUFFER (x, y) = ' ' ;
                             
                        xCaret = 0 ;
                        yCaret = 0 ;
                             
                        InvalidateRect (hwnd, NULL, FALSE) ;
                        break ;
                             
                   default:
    					
                        BUFFER (xCaret, yCaret) = (TCHAR) wParam ;
                        
                        HideCaret (hwnd) ;
                        hdc = GetDC (hwnd) ;
              
                        SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,
                                       dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;
    
                        TextOut (hdc, xCaret * cxChar, yCaret * cyChar,
                                 & BUFFER (xCaret, yCaret), 1) ;
    
                        DeleteObject(
                             SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
                        ReleaseDC (hwnd, hdc) ;
    						if(wParam == '\n')
    						{
    							++yCaret;
    							SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;
    							SendMessage(hwnd, WM_CHAR, lParam, '\r');
    						}
    						if(wParam == '\r')
    							++xCaret;
                        ShowCaret (hwnd) ;
    
                        if (++xCaret == cxBuffer)
                        {
                             xCaret = 0 ;
                             
                             if (++yCaret == cyBuffer)
                                  yCaret = 0 ;
                        }
                        break ;
                   }
              }
              
              SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;
              return 0 ;
              
         case WM_PAINT:
              hdc = BeginPaint (hwnd, &ps) ;
              
              SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,
                                       dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;
                               
     			
              for (y = 0 ; y < cyBuffer ; y++)
                   TextOut (hdc, 0, y * cyChar, & BUFFER(0,y), cxBuffer) ;
    
              DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
              EndPaint (hwnd, &ps) ;
              return 0 ;
              
         case WM_DESTROY:
              PostQuitMessage (0) ;
              return 0 ;
         }
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
    Last edited by juice; 01-23-2012 at 10:56 PM.

  2. #2
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Nice program!

    Using the BUFFER macro with cxBuffer and cyBuffer gives you *(pBuffer + cyBuffer * cxBuffer + cxBuffer), which is cxBuffer too many. Also you need an initial decrement of pNewBuff.

    Try this:
    Code:
    			  pOldBuff = pBuffer + xprev * yprev ;
    			  pNewBuff = pBuffer + cxBuffer * cyBuffer;
    	
    			  while(pNewBuff > pOldBuff)
    			      *--pNewBuff = ' ';
    I'd also get rid of the fall-through from WM_CREATE to WM_SIZE since it's not achieving much (just the SetCaretPos call).
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  3. #3
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    Thanks. That was so easy...

  4. #4
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Easy when it's pointed out!
    That's the problem with macros. They tend to hide details without separating them in the way a real function does (for instance, your macro uses variable names local to the "calling" function).
    So whenever you have a bug that may involve a macro, you should manually expand it in place to clearly see what's happening.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  5. #5
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    In this program when the user hits the enter key then why doesn't the caret come down by two places, because the variable yCaret is incremented twice, once in case '\n' (line no 231) and then again in case '\r' (line no 236).

  6. #6
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    I just want to ask, doesn't both '\n' and '\r' messages get generated when we hit the enter key??

  7. #7
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by juice View Post
    I just want to ask, doesn't both '\n' and '\r' messages get generated when we hit the enter key??
    That's a good question. Interestingly, only the '\r' message is sent as a WM_CHAR message to your program. So apparently TranslateMessage translates a VK_RETURN virtual key code for WM_KEYDOWN/WM_KEYUP combos into a '\r' for WM_CHAR.

    At the lowest level, the keyboard generates OEM specific "scan codes," and presumably only a single code is generated for the Enter key. Anything that happens after that is microsoft madness, such as the end-of-line markers in text files.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  8. #8
    Registered User
    Join Date
    Aug 2011
    Posts
    385
    The problem with this code was that when we hit backspace or delete, the entire lines gets shifted to the left by one position from the current cursor position, instead of moving the contents of the entire screen by one character. I tried to rectify this problem by modifying the the code for VK_DELETE as follows, but the code is not working. Please help..

    Code:
     case VK_DELETE:
         			int temp = 0;
    				for(y = yCaret ; y < cyBuffer; y++)
    				{
    					if(temp == 0)
    					{	 
    							x = xCaret; 
    							temp = 1;
    					} 
    					else 
    							x = 0;
    			  
    				   	for ( ; x < cxBuffer - 1 ; x++)
       		                 BUFFER(x, y) = BUFFER(x + 1, y) ;
    					
    					if(y < cyBuffer - 1)
    						BUFFER(x, y) = BUFFER(0, y + 1);
    				}
                   
                   BUFFER (cxBuffer - 1, cyBuffer - 1) = ' ' ;
                   
                   HideCaret (hwnd) ;
                   hdc = GetDC (hwnd) ;
              
                   SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,
                                       dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;
                   x = xCaret;    
                   for (y = yCaret ; y < cyBuffer ; y++)
    			   {
    					if(x != 0)
                   		{
    						TextOut (hdc, x, y * cyChar, & BUFFER(x,y), cxBuffer - x) ;
    						x = 0;
    					}
    					else
    						TextOut (hdc, 0, y * cyChar, & BUFFER(x,y), cxBuffer) ;
    			   }
    
                   DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
                   ReleaseDC (hwnd, hdc) ;
                   ShowCaret (hwnd) ;
                   break ;
              }
              SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;
              return 0 ;
    Last edited by juice; 02-03-2012 at 05:07 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 48
    Last Post: 09-26-2008, 03:45 AM
  2. Abnormal program termination
    By Kayoss in forum C++ Programming
    Replies: 3
    Last Post: 05-16-2006, 03:29 PM
  3. abnormal program termination
    By Smiley0101 in forum C++ Programming
    Replies: 1
    Last Post: 03-02-2003, 05:04 PM
  4. **///Re: Abnormal prg termination
    By jhsurti in forum C++ Programming
    Replies: 5
    Last Post: 01-07-2003, 02:33 AM
  5. abnormal program termination
    By ProLin in forum C++ Programming
    Replies: 2
    Last Post: 01-20-2002, 09:56 PM