Listing 2 gui.c — Implementation of platform-independent functions

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "gui.h"

extern int              charHeight;
extern FILE*            fErrLog;
extern GUI_APPLICATION* pGuiApplication;

//*** logging function into a file opened by GUI_APPLICATION

void Log(char* fmt, ...)
{
   va_list ap;

   if(fErrLog) {
     va_start(ap, fmt);
     vfprintf(fErrLog, fmt, ap);
     fflush(fErrLog);  // to protect against losing log if crashing
     va_end(ap);
   }
}

//*** Functions for GUI_APPLICATION

int GUI_APPLICATION::AddWindow(GUI_WINDOW *pWindow)
{
   int              ret = 1;
   GUI_WINDOW_ELEM* pTmp;

   // add a GUI_WINDOW to the linked list of windows
   if(pFree) {
     pTmp = pFree;
     pFree = pFree->pNext;
     pTmp->pWindow = pWindow;
     pTmp->pNext = pUsed;
     pUsed = pTmp;
     ret = 0;
   }

   if(ret) Log("Error: too many windows.\n");

   return(ret);
}

int GUI_APPLICATION::DelWindow(GUI_WINDOW* pWindow)
{
   int             ret = 1;
   GUI_WINDOW_ELEM *pTmp, *pPrev;

   // delete a window from the linked lists of windows
   for(pTmp = pUsed, pPrev = NULL; pTmp; pPrev = pTmp,
      pTmp = pTmp->pNext) {
     if(pTmp->pWindow == pWindow) {
       // take out of used list
       if(pPrev) pPrev->pNext = pTmp->pNext;
       else      pUsed        = pTmp->pNext;
       // put into free list
       pTmp->pNext = pFree;
       pFree = pTmp;
       ret = 0;
       break;
     }
   }

   if(ret) Log("Error: can't delete window %p\n", pWindow);

   return(ret);
}

GUI_WINDOW* GUI_APPLICATION::FindWindow(NativeWindow window)
{
   GUI_WINDOW_ELEM *pTmp;

   // find a window in its list of windows
   for(pTmp = pUsed; pTmp; pTmp = pTmp->pNext) {
      if(pTmp->pWindow->GetNativeWindow() == window) break;
   }

   return(pTmp ? pTmp->pWindow : NULL);
}

//*** Functions for GUI_OBJECT

GUI_OBJECT::GUI_OBJECT(GUI_WINDOW* pParent, int id, int x, int y,
                   int width, int height)
          : id(id), pParent(pParent), x(x), y(y),
            width(width), height(height)
{
   // add this object to its parent children list
   if(pParent) pParent->AddChild(this);
}

GUI_OBJECT::~GUI_OBJECT(void)
{
   // delete this object from its parent children list
   if(pParent) pParent->DeleteChild(this);
}

//*** Functions for GUI_GRAPHICS_OBJECT

GUI_GRAPHICS_OBJECT::GUI_GRAPHICS_OBJECT(GUI_WINDOW* pParent, int id,
                                  int x, int y,
                                  int width, int height,
                                  int color, int lineWidth)
                 :GUI_OBJECT(pParent, id, x, y, width, height),
                  color(color), lineWidth(lineWidth)
{
   // nothing to do
}

GUI_GRAPHICS_OBJECT::~GUI_GRAPHICS_OBJECT(void)
{
   // nothing to do
}

//*** Functions for GUI_LINE

GUI_LINE::GUI_LINE(GUI_WINDOW* pParent, int id, int x1, int y1, int x2,
                int y2, int color, int lineWidth)
        :GUI_GRAPHICS_OBJECT(pParent, id, x1, y1, x2, y2, color, lineWidth)
{
   // paint the first time around
   Paint(pParent->GetGraphicsHandle());
}

//*** Functions for GUI_ELLIPSE

GUI_ELLIPSE::GUI_ELLIPSE(GUI_WINDOW* pParent, int id, int x, int y,
                int width, int height,
                int color, int fillType, int lineWidth)
          :GUI_GRAPHICS_OBJECT(pParent, id, x, y, width, height,
                           color, lineWidth),
           fillType(fillType)
{
   // paint the first time around
   Paint(pParent->GetGraphicsHandle());
}

//*** Functions for GUI_WINDOW_OBJECT

GUI_WINDOW_OBJECT::GUI_WINDOW_OBJECT(GUI_WINDOW* pParent, int id,
                                     int x, int y, int width, int height)
                                     :GUI_OBJECT(pParent, id, x, y, width, height)
{
   window = 0;
}

//*** Functions for GUI_WINDOW

int GUI_WINDOW::AddChild(GUI_OBJECT* pChild)
{
   int              ret = 1;
   GUI_OBJECT_ELEM* pTmp;

   // add pChild to the linked list of children
   if(pFree) {
     pTmp = pFree;
     pFree = pFree->pNext;
     pTmp->pObject = pChild;
     pTmp->pNext = pUsed;
     pUsed = pTmp;
     ret = 0;
}

   if(ret) Log("Error: too many children.\n");

   return(ret);
}

int GUI_WINDOW::DeleteChild(GUI_OBJECT* pChild)
{
   int             ret = 1;
   GUI_OBJECT_ELEM *pTmp, *pPrev;

   // delete pChild from the linked list of children
   for(pTmp = pUsed, pPrev = NULL; pTmp; pPrev = pTmp,
      pTmp = pTmp->pNext) {
     if(pTmp->pObject == pChild) {
        // take out of used list
        if(pPrev) pPrev->pNext = pTmp->pNext;
        else      pUsed        = pTmp->pNext;
        // put into free list
        pTmp->pNext = pFree;
        pFree = pTmp;
        ret = 0;
        break;
     }
   }

   if(ret) Log("Error: can't delete child %p\n", pChild);

   return(ret);
// get child pointer from its id; it returns NULL if fails

GUI_OBJECT* GUI_WINDOW::GetChildFromId(int id)
{
   GUI_OBJECT_ELEM *pTmp;

   for(pTmp = pUsed; pTmp; pTmp = pTmp->pNext) {
     if(pTmp->pObject->GetId() == id) break;
   }

   return(pTmp ? pTmp->pObject : NULL);
}

// get child pointer from its native window; it returns NULL if fails

GUI_OBJECT* GUI_WINDOW::GetChildFromWindow(NativeWindow hwnd)
{
   GUI_OBJECT_ELEM *pTmp;

   for(pTmp = pUsed; pTmp; pTmp = pTmp->pNext) {
      if(pTmp->pObject->GetNativeWindow() == hwnd) break;
   }

   return(pTmp ? pTmp->pObject : NULL);
}

/* End of File */