home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1990
/
02
/
paterson.lst
< prev
next >
Wrap
File List
|
1989-12-26
|
7KB
|
311 lines
_MANAGING MULTIPLE DATA SEGMENTS UNDER MICROSOFT WINDOWS: PART I_
by Tim Paterson and Steve Flenniken
[LISTING ONE]
page 78,132
.xlist
include CMACROS.INC
.list
?PLM = 0 ;Use C calling convention
.model medium
.code
cProc memcpyifp,<PUBLIC>,<ds,si,di>
parmD DestIfp
parmD SourceIfp
parmW cb
cBegin
mov bx,SEG_DestIfp
mov dx,bx ;pSeg is high word of return value
mov es,ds:[bx] ;Segment of destination
mov bx,SEG_SourceIfp
mov ds,ds:[bx] ;Segment of source
mov si,OFF_SourceIfp
mov di,OFF_DestIfp
mov ax,di ;Low word of return value
mov cx,cb
;Source in ds:si
;Destination in es:di
;Count in cx
shr cx,1 ;Move by words
rep movsw
jnc EvenBytes ;Was it an even number?
movsb ;Move the odd byte
EvenBytes:
;return value is destination IFP in dx:ax
cEnd
end
[LISTING TWO]
/* segtable.c */
#include "windows.h"
#define GLOBAL
#include "segtable.h"
static PSEG NEAR freelist;
void FAR PASCAL SegmentInit(void)
{
freelist = 0;
cwSegs = MINPSEGS;
DefineHandleTable(SegmentTable);
segDgroup = HIWORD((void FAR *)&segDgroup);
}
PSEG FAR PASCAL SegmentAlloc(DWORD size)
{
PSEG pseg;
HANDLE handle;
if (freelist)
{
if (!(handle = GlobalAlloc(GMEM_MOVEABLE, size)))
return((PSEG)0);
pseg = freelist;
freelist = (PSEG)*freelist;
}
else
{
if (cwSegs >= MAXPSEGS)
return((PSEG)0);
if (!(handle = GlobalAlloc(GMEM_MOVEABLE, size)))
return((PSEG)0);
pseg = &SegmentTable[cwSegs+2];
cwSegs++;
}
*pseg = GlobalSegment(handle);
return(pseg);
}
void FAR PASCAL SegmentFree(PSEG pseg)
{
#if DEBUG
if (!VALID_VARIABLE_PSEG(pseg))
SegmentError();
#endif
if (*pseg)
{
#if DEBUG
if ((*pseg % 2) == 0)
SegmentError();
#endif
GlobalFree((HANDLE)GlobalHandle(*pseg));
}
*(PSEG *)pseg = freelist;
freelist = pseg;
}
void FAR PASCAL DataFree(PSEG pseg)
{
#if DEBUG
if (!VALIDPSEG(pseg) || (*pseg % 2) == 0)
SegmentError();
#endif
GlobalFree((HANDLE)GlobalHandle(*pseg));
*pseg = 0;
}
BOOL FAR PASCAL SegmentRealloc(PSEG pseg, DWORD size)
{
HANDLE handle;
#if DEBUG
if (!VALIDPSEG(pseg))
SegmentError();
#endif
if (*pseg)
{
#if DEBUG
if ((*pseg % 2) == 0)
SegmentError();
#endif
return ( (BOOL) GlobalReAlloc( (HANDLE)GlobalHandle(*pseg), size,
GMEM_MOVEABLE));
}
else
{
if (!(handle = GlobalAlloc(GMEM_MOVEABLE, size)))
return(FALSE);
*pseg = GlobalSegment(handle);
return(TRUE);
}
}
#if DEBUG
void FAR PASCAL SegmentError(void)
{
FatalExit(-1);
}
#endif
[LISTING THREE]
/* segtable.h */
#define MAXPSEGS 9
#define MINPSEGS 1
#define cwSegs SegmentTable[0]
#define cwClear SegmentTable[1]
#define segDgroup SegmentTable[2]
#ifndef GLOBAL
#define GLOBAL extern
#endif
typedef WORD BOOLEAN;
typedef WORD SEG;
typedef SEG NEAR *PSEG;
typedef unsigned long IFP;
#define FARPTR(off, seg) ( (void FAR *)MAKELONG(off, seg) )
#define MAKEIFP(off,pseg) ( (IFP)MAKELONG(off, pseg) )
#define IFP2SEG(ifp) ( *(PSEG)HIWORD(ifp) )
#define IFP2PTR(ifp) FARPTR(LOWORD(ifp), IFP2SEG(ifp))
#define GlobalSegment(handle) ((SEG) HIWORD(GlobalHandle(handle)) )
void FAR PASCAL SegmentInit(void);
PSEG FAR PASCAL SegmentAlloc(DWORD size);
void FAR PASCAL SegmentFree(PSEG pseg);
void FAR PASCAL DataFree(PSEG pseg);
BOOL FAR PASCAL SegmentRealloc(PSEG pseg, DWORD size);
void FAR PASCAL DefineHandleTable(WORD NEAR *segtable);
void FAR PASCAL SegmentError(void);
GLOBAL SEG NEAR SegmentTable[MAXPSEGS + 2];
#define VALIDPSEG(pseg) \
(pseg > &SegmentTable[1] && \
pseg < &SegmentTable[MAXPSEGS + 2] && \
((WORD)pseg % 2) == 0)
#define VALID_VARIABLE_PSEG(pseg) \
(pseg > &SegmentTable[MINPSEGS + 1] && \
pseg < &SegmentTable[MAXPSEGS + 2] && \
((WORD)pseg % 2) == 0)
Examplσ 1║ Samplσ sourcσ codσ fo≥ settinτ asidσ the segment table
/¬ WOR─ defineΣ a≤ unsigneΣ shor⌠ iε windows.Φ */
#definσ MAXPSEG╙ 3░ /¬ ma° ú oµ tablσ segment≤ */
WOR─ SegmentTable[MAXPSEGS+2];
#definσ cwSeg≤ SegmentTable[0]
#definσ cwClea≥ SegmentTable[1]
Examplσ 2║ Sample code for puttting the group into the table
#define segDgroup SegmentTable[2]
segDgroup = HIWORD((void FAR *)&SegDgroup);
++cwSegs; /* was zero, now 1 */
Examplσ 3║ GlobalHandle() converts a handle to a segment
if ( hMem = GlobalAlloc(flags, dwBytes) )
SegmentTable[i] = HIWORD( GlobalHandle(hMem) );
else
/* out of memory */
Examplσ 4║ Macro fo≥ creating a file pointer
#define FARPTR(off,seg) ((void FAR*)MAKELONG(off,seg))
*(WORD FAR *) FARPTR(0,segSheetDescr) = 0;
Examplσ 5║ Macro fo≥ referencinτ ß particula≥ type
#define FARWORD(off,seg) (*(WORD FAR*)FARPTR(off,seg))
FARWORD(0,segSheetDescr) = 0; /* no sheets loaded */
Examplσ 6║ Buildinτ iε ß segment
#define FARDESCR(off) (*(DESCR FAR*)FARPTR (off,segSheetDescr))
typedef struct /* descriptor for a spreadsheet */
{
unsigned short SheetId;
char *SheetName;
...
} DESCR;
FARDESCR(pCurSheet).SheetId = NextSheetNum++;
pCurSheetName = FARDESCR(pCurSheet).SheetName;
Examplσ 7║ Allocating a segment
if ( hMem = GlobalAlloc(flags, dwBytes) )
{
pSeg = &SegmentTable[++cwSegs + 1];
*pSeg = HIWORD( GlobalHandle(hMem) );
}
else
/* out of memory */
Examplσ 8║ Defininτ ß ne≈ datß type
typedef unsigned long IFP;
#define MAKEIFP(off,pseg) ((IFP)MAKELONG(off,pseg))
#define IFP2SEG(ifp⌐ ( *(WORD NEAR *)HIWORD(ifp))
#define IFP2PTR(ifp⌐ FARPTR(LOWORD(ifp),IFP2SEG(ifp))
Examplσ ╣║ ┴ cal∞ t∩ ß general-purposσ blocδ cop∙ routine
IFP memcpyifp(
MAKEIFP(&CurSheetBuf,&segDgroup), /* destination */
MAKEIFP(pCurSheet,&segSheetDescr)¼ /* source */
sizeof(DESCR⌐ /* bytes to copy */
);
Examplσ 10║ Onσ wa∙ t∩ codσ memcpyifp()
IFP memcpyifp(IFP DestIfp, IFP SourceIfp, unsigned cb)
{
unsigned i;
for (i=0; i<cb; i++)
((char FAR *)IFP2PTR(DestIfp))[i] =
((char FAR *)IFP2PTR(SourceIfp))[i];
return(DestIfp);
}
Examplσ 11║ Storinτ pointer≤ iε loca∞ variables
char FAR *Dest;
char FAR *Source;
Dest = IFP2PTR(DestIfp);
Source = IFP2PTR(SourceIfp);
for (i=0; i<cb; i++)
Dest[i] = Source[i];
Examplσ 12║ Writinτ memcpyifp(⌐ usinτ a standard library function
IFP memcpyifp(IFP DestIfp, IFP SourceIfp, unsigned cb)
{
movedata( IFP2SEG(SourceIfp)¼ /* source seg */
LOWORD(SourceIfp), /* source offset */
IFP2SEG(DestIfp), /* destination seg */
LOWORD(DestIfp), /* destination offset */
cb /* count of bytes */
);
return(DestIfp);
}