Porting Communications Software to Windows CE
by Oliver Diener



Listing One
vstdio.h

#ifndef _VSTDIOH_INCLUDED
#define _VSTDIOH_INCLUDED
#include <malloc.h>

extern int sprintf(char *buffer, const char *fmt, ...);
extern int sscanf(char *buffer, const char *fmt, ...);
extern char *ltoa( long value, char *string, int radix );

_inline unsigned char
toupper(unsigned char c)
{
    if (c >= 'a' && c <= 'z') return c-'a'+'A';
    return c;
}
_inline int
isdigit(unsigned char c)
{
    if (c >= '0' && c <= '9') return 1;
    return 0;
}
_inline int
isxdigit(unsigned char c)
{
    if ((c >='0' && c <='9') || (c >='a'&& c <='f') || (c >='A' && c <='F')) 
        return 1;
    return 0;
}
#define ansi2unicode(a) \
( (a) == NULL ? NULL : ( \
    _a_len = MultiByteToWideChar(CP_ACP, 0, a, -1, NULL, 0), \
    _a_p = (unsigned short*) alloca(_a_len*2+2), \
    MultiByteToWideChar(CP_ACP, 0, a, -1, _a_p, _a_len), \
    _a_p) )
#define unicode2ansi(a) \
( (a) == NULL ? NULL : ( \
    _a_len = WideCharToMultiByte(CP_ACP, 0, a, -1, NULL, 0, NULL, NULL), \
   _a_p = (unsigned short*) alloca(_a_len+1), \
   WideCharToMultiByte(CP_ACP, 0, a, -1, (char *)_a_p, _a_len, NULL, NULL), \
    (char *)_a_p) )
#endif /* _VSTDIOH_INCLUDED */
vstdio.c
#ifdef UNICODE
#include <windows.h>
#include <vstdio.h>
#include <tchar.h>
#include <stdarg.h>

#define SMALL   0
#define BIG     1

static char digit[] =
  {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
static char digitbig[] =
    {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
static char *
fillbuf(char *buf, char *src, int len, int leadnull, int digcount)
{
    int  i;
    if (digcount) {
        for (i = (digcount - len); i > 0; i--) {
            if (leadnull) *buf++ = '0';
            else *buf++ = ' ';
        }
    }
    for (i = 0; i < len; i++) {
        *buf++ = *src++;
    }
    return buf;
}
static char *
int2str(char *buf, int val, int leadnull, int digcount, int base, int big)
{
    int b;
    char tmp[1024];
    char *p = tmp;
    if (val < 0) {
        *p++ = '-';
        val *= -1;
    }
    if (val == 0) *p++ = '0';
    for (b = 1; (val/b) >= base; b *= base);
    while (val > 0) {
        if (big == BIG) *p++ = digitbig[(int)(val/b)];
        else *p++ = digit[(int)(val/b)];
        val = val - b * ((int)(val/b));
        b /= base;
    }
    while (b >= 1) {
        *p++ = '0';
        b /= base;
    }
    return fillbuf(buf, tmp, (p-tmp), leadnull, digcount);
}
char *
str2int(char *buf, int *value, int base)
{
    int val, i = 1;
    *value = 0;
    while (*buf == ' ') buf++;
    while (*buf != ' ' && *buf != '\0') {
        if (isdigit(*buf)) val = *buf - '0';
        else if (isxdigit(*buf)) {
            toupper(*buf);
            val = 10 + *buf - 'A';
        }
        *value = *value * i + val;
        i = base;
        buf++;
    }
    return buf;
}
int 
sprintf(char *buffer, const char *fmt, ...)
{
    va_list ap;
    char tmp;
    const char *p;
    char *sval, cval, *q = buffer, *buf = buffer;
    int leadnull, digcount, first, ival;
    char tmp_buf[1024];
    char *p_buf = tmp_buf;

    va_start(ap, fmt); /* ap points to first unnamed argument */
    for (p = fmt; *p; p++) {
        if (*p != '%') {
            *buf++ = *p;
            continue;
        }
       tmp = *++p;
        leadnull = 0;
        digcount = 0;
        first = 1;
        while (isdigit(tmp)) {
            if ((tmp - '0') == 0 && first) {
                leadnull = 1;
            } else {
                digcount = (digcount * 10) + (tmp -'0');
            }
            first = 0;
            tmp = *++p;
        }
        switch(tmp) {
        case 'd':
        case 'i':
            ival = va_arg(ap, int);
            buf = int2str(buf, ival, leadnull, digcount, 10, SMALL);
            break;
        case 'x':
            ival = va_arg(ap, int);
            buf = int2str(buf, ival, leadnull, digcount, 16, SMALL);
            break;
        case 'X':
            ival = va_arg(ap, int);
            buf = int2str(buf, ival, leadnull, digcount, 16, BIG);
            break;
        case 'c':
            cval = va_arg(ap, char);
            *buf++ = cval;
            break;
        case 's':
            for (sval = va_arg(ap, char*); *sval; sval++) 
                *p_buf++ = *sval;       
            buf = fillbuf(buf, tmp_buf, (p_buf-tmp_buf), leadnull, digcount);
            p_buf = tmp_buf;
            break;
        default:
            *buf++ = *p;
            break;
        }
    }
    va_end(ap);
    *buf++ = '\0';
    return (buf - q);
}
int 
sscanf(char *buffer, const char *fmt, ...)
{
    va_list ap;
    int rc = 0;
    const char *p;
    char tmp;
    char *buf = buffer;

    va_start(ap, fmt); /* ap points to first unnamed argument */
    for (p = fmt; *p; p++) {
        if (*p != '%') continue;
        tmp = *++p;
        rc++;

        switch(tmp) {
        case 'd':
        case 'i':
            buf = str2int(buf, *(int **)ap, 10);
            va_arg(ap, int);
            break;
        case 'x':
        case 'X':
            buf = str2int(buf, *(int **)ap, 16);
            va_arg(ap, int);
            break;
        }
    }
    va_end(ap);
    return rc;
}
extern char *
ltoa(long value, char *string, int radix)
{
    string = int2str(string, value, 0, 0, radix, SMALL);
    *string = '\0';
    return string;
}
#endif /* UNICODE */


Listing Two
vfcntl.h
#ifndef _VFCNTLH_INCLUDED
#define _VFCNTLH_INCLUDED

#define _O_RDONLY       0x0000  /* open for reading only */
#define _O_WRONLY       0x0001  /* open for writing only */
#define _O_RDWR         0x0002  /* open for reading and writing */
#define _O_APPEND       0x0008  /* writes done at eof */

#define _O_CREAT        0x0100  /* create and open file */
#define _O_TRUNC        0x0200  /* open and truncate */
#define _O_EXCL         0x0400  /* open only if file doesn't already exist */

#define _O_TEXT         0x4000  /* file mode is text (translated) */
#define _O_BINARY       0x8000  /* file mode is binary (untranslated) */

#define O_RDONLY        _O_RDONLY
#define O_WRONLY        _O_WRONLY
#define O_RDWR          _O_RDWR
#define O_APPEND        _O_APPEND
#define O_CREAT         _O_CREAT
#define O_TRUNC         _O_TRUNC
#define O_EXCL          _O_EXCL
#define O_TEXT          _O_TEXT
#define O_BINARY        _O_BINARY
#define O_RAW           _O_BINARY
#define O_TEMPORARY     _O_TEMPORARY
#define O_NOINHERIT     _O_NOINHERIT
#define O_SEQUENTIAL    _O_SEQUENTIAL
#define O_RANDOM        _O_RANDOM

#endif /* _VFCNTL_INCLUDED */

vio.h
#ifndef _VIOH_INCLUDED
#define _VIOH_INCLUDED

extern int open( const char *filename, int oflag);
extern int write( int handle, const void *buffer, unsigned int count );
extern int close( int handle );

#endif /* _VIOH_INCLUDED */

vio.c
#ifdef _WIN32_WCE
#include <windows.h>
#include <tchar.h>
#include <luca/mach.h>
#include <luca/vfcntl.h>
#include <luca/vstdio.h>

int open( const char *filename, int oflag)
{
    V_USES_CONVERSION
    DWORD access = 0, creation = 0; 
    if (oflag & O_RDONLY) access = GENERIC_READ;
    else if (oflag & O_WRONLY) access = GENERIC_WRITE;
    else if (oflag & O_RDWR) access = (GENERIC_WRITE | GENERIC_READ);
   if ((oflag & O_APPEND) && (oflag & O_CREAT)) creation = OPEN_ALWAYS;
    else if (oflag & O_APPEND) creation = OPEN_EXISTING;
    else if (oflag & O_CREAT) creation = CREATE_NEW;
    
    return (int) CreateFile(VTEXT(filename), access, 0, NULL,
                                 creation, FILE_ATTRIBUTE_NORMAL, NULL);
}
int write( int handle, const void *buffer, unsigned int count )
{
    DWORD counter;
    WriteFile((void*) handle, buffer, count, &counter, NULL);
    return counter;
}
int close( int handle )
{
    return CloseHandle((void*) handle);
}
#endif /* _WIN32_WCE */


Listing Three
void CFaxDlg::OnSend() 
{
    USES_CONVERSION;                // see MSDN TN059 
    Vport fax;                      // LUCA port object
    CString faxno, text, linkid;
    const char *linkid_ascii, *text_ascii;

    EditFaxNo.GetWindowText(faxno);     // get faxno from edit control 
    EditText.GetWindowText(text);       // get message text from edit control

    linkid = _T("sff/fax/atmodem:") + faxno + 
                                 _T("/async/com:1,speed=19200,flow=xonxoff");
                // LUCA link identifer: use structured fax format converter 
                // (SFF) over class 2 fax transmission (FAX) via Hayes 
                // compatible modem (ATMODEM) connected to COM1 (COM) 
    linkid_ascii = T2CA(linkid);            // convert UNICODE to ASCII
    text_ascii = T2CA(text);

    fax.Vopen(linkid_ascii);        // open LUCA port, start dialing 
    fax.Vctl(V_WTIMEOUT, 60000);    // set write timeout
    fax.Vwrite(text_ascii, strlen(text_ascii)); // send message
    fax.Vclose();                   // close connection, LUCA will wait until 
                                    // your fax has been sent
}








5


