Release 0.3.0
Fri Sep 3 11:52:18 1993 Bob Amstadt
* [windows/timer.c]
Changed to use CallWindowProc() rather directly calling callback.
* [windows/event.c]
Implemented SetCapture() and ReleaseCapture()
* [windows/keyboard.c]
Created stub for GetKeyState()
* [objects/linedda.c]
Created stub for LineDDA()
* [if1632/callback.c]
Created callback handler for LineDDA callback procedure.
* [if1632/callback.c]
Created FreeProcInstance()
Fri Sep 3 08:36:52 1993 David Metcalfe
* [loader/signal.c]
Patch to and code for INT 1A
Thu Sep 2 00:31:54 1993 Alexandre Julliard
* [objects/font.c] [objects/text.c]
More text support: implemented justification and underlining.
* [windows/clipping.c] [objects/clipping.c]
Moved low-level clipping functions to objects/clipping.c.
* [windows/clipping.c] [windows/event.c] [windows/message.c]
Implemented window update regions.
* [windows/dc.c] [objects/dcvalues.c]
Moved some device-independent DC functions to objects/dcvalues.c.
* [windows/graphics.c]
Implemented InvertRect() and GetPixel().
Sat Aug 28 08:40:23 1993 Eric Youngdale
* [include/neexe.h] [loader/wine.c]
Added code to handle relocation type 4.
* [loader/signal.h] [loader/wine.c] [loader/selector.c]
Added support for dos interrupts.
Thu 26 Aug 19:15:00 1993 Eric Youngdale
* [loader/selector.c]
Fixed bug dealing with loading DLLs.
Thu Aug 26 19:22:40 1993 Alexandre Julliard
* [include/gdi.h] [objects/font.c] [windows/dc.c]
Beginning of real font support.
* [windows/graphics.c]
Implemented PatBlt().
* [memory/global.c]
Corrected a bug with linked list handling in GlobalAlloc().
* [objects/bitmap.c]
Corrected a bug in BITMAP_SelectObject().
Tue Aug 24 19:22:40 1993 David Metcalfe
* [controls/Command*] [controls/Label*] [controls[MenuButto*]
[controls/SmeMenuButt*]
Change code to support & as a special character in menu item text.
Tue Aug 24 19:22:40 1993 Alexandre Julliard
* [include/gdi.h] [windows/dc.c]
Heavily modified the DC structure for better device-independence.
* [objects/bitmap.c]
Implemented bitmap dimensions.
* [windows/dc.c] [windows/dce.c]
Implemented DC state saving and restoring.
* [windows/dc.c]
Implemented ROP mode.
* [windows/graphics.c]
Implemented FillRect().
Mon Aug 23 22:08:34 1993 Bob Amstadt (bob at pooh)
* [misc/xt.c]
Fixed bug in InvalidateRect(). Solitaire attempted to
clear window before it was realized.
* [loader/resource.c]
Began rewrite of LoadBitmap().
* [loader/wine.c]
Fixed code which set Argv and Argc global variables.
* [loader/selector.c]
Added code to set up command line arguments.
* [include/neexe.h]
Fixed error in PSP structure.
Tue Aug 17 20:41:12 1993 Alexandre Julliard
* [include/gdi.h] [windows/dc.c]
Implemented device capabilities.
* [objects/region.c]
Implemented EqualRgn() and CombineRgn().
* [windows/clipping.c]
Implemented Save/RestoreVisRgn().
* [windows/graphics.c]
Implemented PaintRgn() and FillRgn().
* [windows/mapping.c]
Implemented mapping modes.
Tue Aug 10 14:07:38 1993 Alexandre Julliard
* [if1632/user.spec] [misc/rect.c]
Implemented rectangle API functions.
* [if1632/gdi.spec] [include/gdi.h] [objects/region.c]
Implemented regions.
* [windows/class.c]
Corrected a typo in UnregisterClass().
* [windows/clipping.c] [windows/dc.c]
Implemented DC clipping and visible region.
Tue Aug 10 20:57:56 1993 Bob Amstadt (bob at pooh)
* [controls/menu.c] [windows/win.c]
SetMenu(), GetMenu(), CheckMenuItem() implemented
Thu Aug 5 22:33:22 1993 Bob Amstadt (bob at pooh)
* [controls/menu.c] [windows/win.c]
Many improvements menus. LoadMenu() should work.
Wed Aug 4 14:55:36 1993 Alexandre Julliard
* [objects/dib.c]
Started the implementation of device-independent bitmaps.
* [objects/bitmap.c]
Added support for multiple bitmap depths.
* [objects/brush.c]
Implemented pattern brushes.
* [windows/dc.c] [windows/graphics.c]
Implemented some GDI graphics primitives.
Tue Aug 3 21:16:47 1993 Bob Amstadt (bob at pooh)
* [controls/menu.c] [windows/win.c] [include/menu.h]
Code to load class menus from executable file.
* [if1632/user.spec]
Fixed specification of SendMessage() and PostMessage.
Mon Jul 26 21:53:24 1993 Alexandre Julliard
* [if1632/call.S]
Corrected a bug in KERNEL_InitTask().
* [include/windows.h]
Added a lot of constants.
* [loader/selector.c]
Corrected a bug in segment allocation in CreateSelectors().
* [objects/bitmap.c]
Implemented SelectObject() for bitmaps.
* [objects/brush.c]
Implemented hatched brushes and SelectObject().
* [objects/gdiobj.c]
Removed linked list (not needed).
* [objects/palette.c]
Implemented system palette creation and misc. palette API functions.
* [windows/timer.c]
Implemented timers.
* [windows/dc.c]
Implemented memory device contexts.
Tue Jul 20 10:38:59 1993 Bob Amstadt (bob at pooh)
* [dos.c]
Split DOS3Call() out of kernel.c. Added support for get date
and time functions.
* [call.S]
Added function ReturnFromRegisterFunc() to allow DOS calls
to return values in registers.
* [regfunc.h]
Macros to access registers saved on stack.
Tue Jul 20 10:38:59 1993 Alexandre Julliard
* [win.c]
Corrected allocation of the WM_CREATE data structure.
* [dce.c] [dce.h]
Implemented DCE handling.
* [bitmap.c] [brush.c] [dc.c] [font.c] [gdi.h] [gdi.spec]
[gdiobj.c] [palette.c] [pen.c]
Implemented the GDI objects data structures and allocation.
* [windows.h]
Added several structures and constants for GDI objects.
Mon Jul 19 12:51:10 1993 Bob Amstadt (bob at pooh)
* [ldtlib.c]
Modified system calls to match Linus' new interface for
the LDT modification.
* [win.c]
Fixed bug with WM_CREATE message.
* [heap.c] [kernel.spec]
Completed local heap allocation functions.
* [global.c]
Created function GlobalQuickAlloc() for easy allocation from DLLs
diff --git a/memory/global.c b/memory/global.c
new file mode 100644
index 0000000..3edfbbe
--- /dev/null
+++ b/memory/global.c
@@ -0,0 +1,723 @@
+static char RCSId[] = "$Id: global.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
+static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "prototypes.h"
+#include "heap.h"
+#include "segmem.h"
+
+/*
+ * Global memory pool descriptor. Segments MUST be maintained in segment
+ * ascending order. If not the reallocation routine will die a horrible
+ * death.
+ *
+ * handle = 0, this descriptor contains the address of a free pool.
+ * != 0, this describes an allocated block.
+ *
+ * sequence = 0, this is not a huge block
+ * > 0, this is a portion of a huge block
+ * =-1, this is a free segment
+ *
+ * addr - address of this memory block.
+ *
+ * length - used to maintain huge blocks.
+ *
+ */
+typedef struct global_mem_desc_s
+{
+ struct global_mem_desc_s *next;
+ struct global_mem_desc_s *prev;
+ unsigned short handle;
+ short sequence;
+ void *addr;
+ int length;
+ int lock_count;
+} GDESC;
+
+GDESC *GlobalList = NULL;
+static unsigned short next_unused_handle = 1;
+
+
+/**********************************************************************
+ * GlobalGetFreeSegments
+ */
+GDESC *
+GlobalGetFreeSegments(unsigned int flags, int n_segments)
+{
+ struct segment_descriptor_s *s;
+ GDESC *g;
+ GDESC *g_start;
+ GDESC *g_prev;
+ int count, i;
+
+ /*
+ * Try to find some empty segments in our list.
+ */
+ count = 0;
+ for (g = GlobalList; g != NULL && count != n_segments; g = g->next)
+ {
+ if ((int) g->sequence == -1)
+ {
+ if (count > 0)
+ {
+ if (g->prev->handle + 8 != g->handle)
+ count = 0;
+ else
+ count++;
+ }
+ else
+ {
+ g_start = g;
+ count = 1;
+ }
+ }
+ else if (count)
+ count = 0;
+ }
+
+ /*
+ * If we couldn't find enough segments, then we need to create some.
+ */
+ if (count != n_segments)
+ {
+ /*
+ * Find list tail.
+ */
+ g_prev = NULL;
+ for (g = GlobalList; g != NULL; g = g->next)
+ g_prev = g;
+
+ /*
+ * Allocate segments.
+ */
+ for (count = 0; count < n_segments; count++)
+ {
+ s = GetNextSegment(flags, 0x10000);
+ if (s == NULL)
+ return NULL;
+
+ g = (GDESC *) malloc(sizeof(*g));
+
+ g->prev = g_prev;
+ g->next = NULL;
+ g->handle = s->selector;
+ g->sequence = -1;
+ g->addr = s->base_addr;
+ g->length = s->length;
+ if (!(flags & GLOBAL_FLAGS_MOVEABLE))
+ g->lock_count = 1;
+ else
+ g->lock_count = 0;
+
+ free(s);
+
+ if (count == 0)
+ g_start = g;
+
+ if (g_prev != NULL)
+ {
+ g_prev->next = g;
+ g->prev = g_prev;
+ }
+ else
+ GlobalList = g;
+ }
+ }
+
+ /*
+ * We have all of the segments we need. Let's adjust their contents.
+ */
+ g = g_start;
+ for (i = 0; i < n_segments; i++, g = g->next)
+ {
+ g->sequence = i + 1;
+ g->length = n_segments;
+ }
+
+ return g_start;
+}
+
+/**********************************************************************
+ * GlobalAlloc
+ */
+unsigned int
+GlobalAlloc(unsigned int flags, unsigned long size)
+{
+ GDESC *g;
+ GDESC *g_prev;
+ void *m;
+
+ /*
+ * If this block is fixed or very big we need to allocate entire
+ * segments.
+ */
+ if (size > 0x8000 || !(flags & GLOBAL_FLAGS_MOVEABLE))
+ {
+ int segments = (size >> 16) + 1;
+
+ g = GlobalGetFreeSegments(flags, segments);
+ if (g == NULL)
+ return 0;
+ else
+ return g->handle;
+ }
+ /*
+ * Otherwise we just need a little piece of a segment.
+ */
+ else
+ {
+ /*
+ * Try to allocate from active free lists.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == 0 && g->sequence == 0)
+ {
+ m = HEAP_Alloc((MDESC **) g->addr, 0, size);
+ if (m != NULL)
+ break;
+ }
+ }
+
+ /*
+ * If we couldn't get the memory there, then we need to create
+ * a new free list.
+ */
+ if (g == NULL)
+ {
+ g = GlobalGetFreeSegments(0, 1);
+ if (g == NULL)
+ return 0;
+
+ g->handle = 0;
+ g->sequence = 0;
+ HEAP_Init((MDESC **) g->addr, (MDESC **) g->addr + 1,
+ 0x10000 - sizeof(MDESC **));
+ m = HEAP_Alloc((MDESC **) g->addr, flags & GLOBAL_FLAGS_ZEROINIT,
+ size);
+ if (m == NULL)
+ return 0;
+ }
+
+ /*
+ * Save position of heap descriptor.
+ */
+ g_prev = g;
+
+ /*
+ * We have a new block. Let's create a GDESC entry for it.
+ */
+ g = malloc(sizeof(*g));
+#ifdef DEBUG_HEAP
+ printf("New GDESC %08x\n", g);
+#endif
+ if (g == NULL)
+ return 0;
+
+ g->handle = next_unused_handle;
+ g->sequence = 0;
+ g->addr = m;
+ g->length = size;
+ g->next = g_prev->next;
+ if (g->next) g->next->prev = g;
+ g->lock_count = 0;
+
+ g_prev->next = g;
+ g->prev = g_prev;
+
+ next_unused_handle++;
+ if ((next_unused_handle & 7) == 7)
+ next_unused_handle++;
+
+#ifdef DEBUG_HEAP
+ printf("GlobalAlloc: returning %04x\n", g->handle);
+#endif
+ return g->handle;
+ }
+}
+
+/**********************************************************************
+ * GlobalFree
+ *
+ * Windows programs will pass a handle in the "block" parameter, but
+ * this function will also accept a 32-bit address.
+ */
+unsigned int
+GlobalFree(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ if (block & 0xffff0000)
+ {
+ for (g = GlobalList; g != NULL; g = g->next)
+ if (g->handle > 0 && (unsigned int) g->addr == block)
+ break;
+ }
+ else
+ {
+ for (g = GlobalList; g != NULL; g = g->next)
+ if (g->handle == block)
+ break;
+ }
+ if (g == NULL)
+ return block;
+
+ /*
+ * If the sequence number is zero then use HEAP_Free to deallocate
+ * memory, and throw away this descriptor.
+ */
+ if (g->sequence == 0)
+ {
+ HEAP_Free((MDESC **) ((int) g->addr & 0xffff0000), (void *) g->addr);
+
+ g->prev->next = g->next;
+
+ if (g->next != NULL)
+ g->next->prev = g->prev;
+
+ free(g);
+ }
+
+ /*
+ * Otherwise just mark these descriptors as free.
+ */
+ else
+ {
+ int i, limit;
+
+ limit = g->length;
+ for (i = g->sequence - 1; i < limit && g != NULL; i++, g = g->next)
+ {
+ g->sequence = -1;
+ g->length = 0x10000;
+ }
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * GlobalLock
+ *
+ */
+void *
+GlobalLock(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block)
+ {
+ g->lock_count++;
+#ifdef DEBUG_HEAP
+ printf("GlobalLock: returning %08x\n", g->addr);
+#endif
+ return g->addr;
+ }
+ }
+
+#ifdef DEBUG_HEAP
+ printf("GlobalLock: returning %08x\n", 0);
+#endif
+ return NULL;
+}
+
+/**********************************************************************
+ * GlobalUnlock
+ *
+ */
+int
+GlobalUnlock(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block && g->lock_count > 0)
+ {
+ g->lock_count--;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/**********************************************************************
+ * GlobalFlags
+ *
+ */
+unsigned int
+GlobalFlags(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block)
+ return g->lock_count;
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * GlobalSize
+ *
+ */
+unsigned int
+GlobalSize(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block)
+ return g->length;
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * GlobalHandle
+ *
+ * This routine is not strictly correct. MS Windows creates a selector
+ * for every locked global block. We do not. If the allocation is small
+ * enough, we only give out a little piece of a selector. Thus this
+ * function cannot be implemented.
+ */
+unsigned int
+GlobalHandle(unsigned int selector)
+{
+ GDESC *g;
+
+ if (selector == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == selector)
+ {
+ if (g->sequence > 0)
+ return g->handle;
+ else
+ {
+ fprintf(stderr, "Attempt to get a handle "
+ "from a selector to a far heap.\n");
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * GlobalCompact
+ *
+ */
+unsigned int
+GlobalCompact(unsigned int desired)
+{
+ GDESC *g;
+ unsigned char free_map[512];
+ unsigned int max_selector_used = 0;
+ unsigned int i;
+ unsigned int selector;
+ int current_free;
+ int max_free;
+
+ /*
+ * Initialize free list to all items not controlled by GlobalAlloc()
+ */
+ for (i = 0; i < 512; i++)
+ free_map[i] = -1;
+
+ /*
+ * Traverse table looking for used and free selectors.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ /*
+ * Check for free segments.
+ */
+ if (g->sequence == -1)
+ {
+ free_map[g->handle >> 3] = 1;
+ if (g->handle > max_selector_used)
+ max_selector_used = g->handle;
+ }
+
+ /*
+ * Check for heap allocated segments.
+ */
+ else if (g->handle == 0)
+ {
+ selector = (unsigned int) g->addr >> 16;
+ free_map[selector >> 3] = 0;
+ if (selector > max_selector_used)
+ max_selector_used = selector;
+ }
+ }
+
+ /*
+ * All segments past the biggest selector used are free.
+ */
+ for (i = (max_selector_used >> 3) + 1; i < 512; i++)
+ free_map[i] = 1;
+
+ /*
+ * Find the largest free block of segments
+ */
+ current_free = 0;
+ max_free = 0;
+ for (i = 0; i < 512; i++)
+ {
+ if (free_map[i] == 1)
+ {
+ current_free++;
+ }
+ else
+ {
+ if (current_free > max_free)
+ max_free = current_free;
+ current_free = 0;
+ }
+ }
+
+ return max_free << 16;
+}
+
+/**********************************************************************
+ * GlobalReAlloc
+ *
+ */
+unsigned int
+GlobalReAlloc(unsigned int block, unsigned int new_size, unsigned int flags)
+{
+ GDESC *g;
+ unsigned int n_segments;
+ int i;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block)
+ break;
+ }
+
+ if (g == NULL)
+ return 0;
+
+ /*
+ * If this is a heap allocated block, then use HEAP_ReAlloc() to
+ * reallocate the block. If this fails, call GlobalAlloc() to get
+ * a new block.
+ */
+ if (g->sequence = 0)
+ {
+ MDESC **free_list;
+ void *p;
+
+ free_list = (MDESC **) ((unsigned int) g->addr & 0xffff0000);
+ p = HEAP_ReAlloc(free_list, g->addr, new_size, flags) ;
+ if (p == NULL)
+ {
+ unsigned int handle = GlobalAlloc(flags, new_size);
+ if (handle == 0)
+ return 0;
+ p = GlobalLock(handle);
+ memcpy(p, g->addr, g->length);
+ GlobalUnlock(handle);
+ GlobalFree(g->handle);
+
+ return handle;
+ }
+ else
+ {
+ g->addr = p;
+ g->length = new_size;
+ return g->handle;
+ }
+ }
+
+ /*
+ * Otherwise, we need to do the work ourselves. First verify the
+ * handle.
+ */
+ else
+ {
+ if (g->sequence != 1)
+ return 0;
+
+ /*
+ * Do we need more memory? Segments are in ascending order in
+ * the GDESC list.
+ */
+ n_segments = (new_size >> 16) + 1;
+ if (n_segments > g->length)
+ {
+ GDESC *g_new;
+ GDESC *g_start = g;
+ int old_segments = g_start->length;
+ unsigned short next_handle = g_start->handle;
+
+ for (i = 1; i <= n_segments; i++, g = g->next)
+ {
+ /*
+ * If we run into a block allocated to something else,
+ * try GlobalGetFreeSegments() and memcpy(). (Yuk!)
+ */
+ if (g->sequence != i || g->handle != next_handle)
+ {
+ g = GlobalGetFreeSegments(flags, n_segments);
+ if (g == NULL)
+ return 0;
+
+ memcpy(g->addr, g_start->addr,
+ g_start->length << 16);
+
+ GlobalFree(block);
+ return g->handle;
+ }
+
+ /*
+ * Otherwise this block is used by us or free. So,
+ * snatch it. If this block is new and we are supposed to
+ * zero init, then do some erasing.
+ */
+ if (g->sequence == -1 && (flags & GLOBAL_FLAGS_ZEROINIT))
+ memset(g->addr, 0, 0x10000);
+
+ g->sequence = i;
+ g->length = n_segments;
+ next_handle += 8;
+
+ /*
+ * If the next descriptor is non-existant, then use
+ * GlobalGetFreeSegments to create them.
+ */
+ if (i != n_segments && g->next == NULL)
+ {
+ g_new = GlobalGetFreeSegments(flags, n_segments - i);
+ if (g_new == NULL)
+ return 0;
+ GlobalFree(g_new->handle);
+ }
+ }
+
+ return g_start->handle;
+ }
+
+ /*
+ * Do we need less memory?
+ */
+ else if (n_segments < g->length)
+ {
+ GDESC *g_free;
+
+ g_free = g;
+ for (i = 0; i < n_segments; i++)
+ {
+ if (g_free->sequence != i + 1)
+ return 0;
+ g_free = g_free->next;
+ }
+ }
+
+ /*
+ * We already have exactly the right amount of memory.
+ */
+ else
+ return block;
+ }
+
+ /*
+ * If we fall through it must be an error.
+ */
+ return 0;
+}
+
+/**********************************************************************
+ * GlobalQuickAlloc
+ */
+void *
+GlobalQuickAlloc(int size)
+{
+ unsigned int hmem;
+
+ hmem = GlobalAlloc(GLOBAL_FLAGS_MOVEABLE, size);
+ if (hmem == 0)
+ return NULL;
+ else
+ return GlobalLock(hmem);
+}
+
+/**********************************************************************
+ * GlobalHandleFromPointer
+
+ */
+unsigned int
+GlobalHandleFromPointer(void *block)
+{
+ GDESC *g;
+
+ if (block == NULL)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ if (g->handle > 0 && g->addr == block)
+ break;
+
+ if (g == NULL)
+ return 0;
+ else
+ return g->handle;
+}
+
+
+