/*  LINKLIST.C
	by Mike Wallace
	Windows Programmer's Journal
	Volume 1 Number 1
	Copyright 1992
*/

/* linked list windows application */
#include <windows.h>
#include <stdio.h>
#include "linklist.h"

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
                    LPSTR lpszCmdLine, int nCmdShow)
{

        HWND hWnd;
        MSG msg;
        WNDCLASS wndclass;

        ghInstance = hInstance;

        if(!hPrevInstance)
        {
                wndclass.style = CS_HREDRAW | CS_VREDRAW;
                wndclass.lpfnWndProc = WndProc;
                wndclass.cbClsExtra = 0;
                wndclass.cbWndExtra = 0;
                wndclass.hInstance = hInstance;
                wndclass.hIcon = LoadIcon (hInstance, ProgName);
                wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
                wndclass.hbrBackground = GetStockObject (WHITE_BRUSH);
                wndclass.lpszMenuName = ProgName;
                wndclass.lpszClassName = ProgName;

                if (!RegisterClass (&wndclass)) return FALSE;

        }

        hWnd = CreateWindow (
                ProgName,
                ProgName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL);

        ShowWindow (hWnd, nCmdShow);
        UpdateWindow (hWnd);

        while (GetMessage (&msg, NULL, 0, 0))
        {
                TranslateMessage (&msg);
                DispatchMessage (&msg);
        }
        return msg.wParam;
} /* WinMain */

long FAR PASCAL WndProc (HWND hWnd, unsigned Msg, WORD wParam, LONG lParam)
{

        switch (Msg)
        {
                case WM_COMMAND:
                        switch (wParam)
                        {
                        case IDM_RUN:
                                MakeList (hWnd);
  	   								  MessageBox (hWnd, "Done", "Hey", MB_OK);  
                                break;
                        
                        case IDM_QUIT:
                                DestroyWindow (hWnd);
                                break;
                        }
                        break;
                case WM_DESTROY:
                        PostQuitMessage (0);
                        break;
                default:
                        return DefWindowProc (hWnd, Msg, wParam, lParam);
        }
        return (0L);
} /* WndProc */

/****************************************/
/*                                      */
/*                                      */
/****************************************/

void FAR PASCAL MakeList (HWND hWnd)
{
	/* local variables */
	short           i;
	static HANDLE   hMem, hMem2, hMem3;

	/* structure of each node in linked list */
	typedef struct _listmarker {

		short   value;
		HANDLE  next;

	} ListMarker;

	/* declare a far pointer to the above structure */
	typedef ListMarker FAR *LISTMARKER;

	LISTMARKER tailPos, tempPos, headPos;

	/* pointer to output file */
	FILE	*fp;

	/* Open output file for writing */
	fp= fopen("data.out", "w");

	/* Build initial linked list of the numbers 1 to 10 */
	if((hMem= GlobalAlloc(GMEM_DISCARDABLE | GMEM_MOVEABLE, 
		sizeof(ListMarker))) == NULL) {

		/* Not enough memory, so beep, show a message and return */
		MessageBeep(0);
		MessageBox(hWnd, "Out of allocation memory!", "ERROR", MB_OK);

		return;
			
	}

	/* Lock the first node, save a value, set next to NULL and unlock */
	tailPos= headPos= (LISTMARKER) GlobalLock(hMem);
	headPos->value= 1;
	headPos->next= NULL;
	GlobalUnlock(hMem);
	
	for (i=2; i < 11; i++) {
			
		/* setup index lookup lists */
		if((tailPos->next= GlobalAlloc(GMEM_DISCARDABLE | GMEM_MOVEABLE, 
			sizeof(ListMarker))) == NULL) {
	
			MessageBeep(0);
			MessageBox(hWnd, "Out of allocation memory!", "ERROR",
							MB_OK);

			return;
					
		}  /* If - End */

		/* Lock the next node, save the value, and set its next to NULL */
		hMem2= tailPos->next;
		tempPos= (LISTMARKER) GlobalLock(hMem2);
		tailPos= tempPos;
		tailPos->value= i;
		tailPos->next= NULL;

		GlobalUnlock(hMem2);
					
	}  /* While - End */

	/* Lock the 1st node and write out its "value" field */
	tailPos= headPos= (LISTMARKER) GlobalLock(hMem);
	fprintf(fp, "%d\n", tailPos->value);

	/* Save the handle to the next node */
	hMem2= tailPos->next;

	/* Unlock the 1st node */
	GlobalUnlock(hMem);

	/* Go through list and print out "value" until no more nodes */
	while (hMem2 != NULL) {
		
		/* Lock the next node and save to tailPos */
		tempPos= (LISTMARKER) GlobalLock(hMem2);
		tailPos= tempPos;

		fprintf(fp, "%d\n", tailPos->value);

		/* Get the handle to the next node and then unlock the current one */
		hMem2= tailPos->next;
		GlobalUnlock(hMem2);
							
	} /* While - End */

	/* Close the output file */
	fclose(fp);					

	/* free nodes in the list */
	tempPos= (LISTMARKER) GlobalLock(hMem);
	hMem2= tempPos->next;
	tempPos= (LISTMARKER) GlobalLock(tempPos->next);
	GlobalUnlock(hMem);
	GlobalFree(hMem);

	while(tempPos->next != NULL) {

	   hMem3= tempPos->next;
	   tempPos= (LISTMARKER) GlobalLock(tempPos->next);
	   GlobalUnlock(hMem2);
	   GlobalFree(hMem2);
	   hMem2=hMem3;

	}

	GlobalUnlock(hMem2);
	GlobalFree(hMem2);

	return;

} /* MakeList */


