jacob navia said:
Yes. I just wanted to point out that for applications where
performance is important C is still the only choice left.
Of course we have discussed about one data point:
memory requirements.
Another point is raw performance, what I will discuss in a next
post.
As a point of interest I decided to write a notepad in C, to run under
Windows.
It took less than three hours to put together, but it isn't quite
releaseable yet - a real user would wnat icons and shortcuts and some safety
against accidentally deleting text. It also hasn't had any more than minimal
testing.
The executable was an acceptable 44k, but the meory footprint was 2MB - more
than I had on my first Windows 3.1 machine
If you look at how the lines are being used, most are to "gift wrap"
functions to open and close files. Most of the rest is boilerplate code -
the FillMenus() function was lifted from another program, and the strings
changed, for example.
I don't know if this is a comment on C or on the libraries.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ID_TEXT_EDT 1
#define ID_NEW_MNU 101
#define ID_OPEN_MNU 102
#define ID_SAVEME_MNU 103
#define ID_SAVEAS_MNU 104
#define ID_EXIT_MNU 105
void RegisterAsciiEditor(HINSTANCE hInstance);
HWND CreateAsciiEditor(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void CreateChildren(HWND hwnd);
static void FillMenus(HWND hwnd);
void Resize(HWND hwnd, int width, int height);
void DoNew(HWND hwnd);
void DoOpen(HWND hwnd);
void DoSave(HWND hwnd);
void DoSaveAs(HWND hwnd);
char *GetOpenFile(HWND hwnd);
char *GetSaveFile(HWND hwnd);
static char *loadfile(char *path);
static int savefile(char *path, char *str);
static char *mystrdup(char *str);
static char filename[MAX_PATH];
/*
Windows main routine
*/
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpcmdline, int nCmdShow)
{
MSG msg;
RegisterAsciiEditor(hInstance);
CreateAsciiEditor(hInstance, nCmdShow);
while(GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
/*
register main window class
*/
void RegisterAsciiEditor(HINSTANCE hInstance)
{
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
//wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MANDICON));
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) (COLOR_MENU + 1);
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = "asciiedit";
//wndclass.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MANDICON));
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wndclass);
}
/*
Create main window
*/
HWND CreateAsciiEditor(HINSTANCE hInstance, int nCmdShow)
{
HWND answer;
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = 201;
rect.bottom = 201;
AdjustWindowRectEx(&rect, 0, 0, WS_EX_CLIENTEDGE);
answer = CreateWindowEx(
WS_EX_CLIENTEDGE,
"asciiedit",
"Ascii Editor",
WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_SIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
rect.right,
rect.bottom,
NULL,
NULL,
hInstance,
NULL
);
FillMenus(answer);
ShowWindow(answer, nCmdShow);
UpdateWindow(answer);
return answer;
}
/*
main window procedure
*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
strcpy(filename, "");
CreateChildren(hwnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_SIZE:
Resize(hwnd, LOWORD(lParam), HIWORD(lParam) );
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_NEW_MNU:
DoNew(hwnd);
break;
case ID_OPEN_MNU:
DoOpen(hwnd);
break;
case ID_SAVEME_MNU:
DoSave(hwnd);
break;
case ID_SAVEAS_MNU:
DoSaveAs(hwnd);
break;
case ID_EXIT_MNU:
DestroyWindow(hwnd);
break;
}
break;
return 0;
}
return DefWindowProc(hwnd, msg,wParam, lParam);
}
/*
Create Child controls
*/
void CreateChildren(HWND hwnd)
{
RECT rect;
HWND hctl;
GetClientRect(hwnd, &rect);
hctl = CreateWindow(
"edit",
"",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL ,
rect.left,
rect.top + 30,
rect.right - rect.left,
rect.bottom - rect.top - 30,
hwnd,
(HMENU) ID_TEXT_EDT,
(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
0);
ShowWindow(hctl, SW_SHOWNORMAL);
}
/*
Set up menus
*/
static void FillMenus(HWND hwnd)
{
HMENU hmenu;
HMENU hfile;
hfile = CreateMenu();
AppendMenu(hfile, MF_STRING, ID_NEW_MNU, "New");
AppendMenu(hfile, MF_STRING, ID_OPEN_MNU, "Open ...");
AppendMenu(hfile, MF_STRING, ID_SAVEME_MNU, "Save");
AppendMenu(hfile, MF_STRING, ID_SAVEAS_MNU, "Save As ...");
AppendMenu(hfile, MF_STRING, ID_EXIT_MNU, "Exit");
hmenu = CreateMenu();
AppendMenu(hmenu, MF_POPUP | MF_STRING, (int) hfile, "File");
SetMenu(hwnd, hmenu);
}
/*
handle resizes
*/
void Resize(HWND hwnd, int width, int height)
{
HWND hedt;
hedt = GetDlgItem(hwnd, ID_TEXT_EDT);
MoveWindow(hedt,
0,
0,
width,
height,
TRUE);
}
/*
create an empty file
*/
void DoNew(HWND hwnd)
{
SetWindowText(hwnd, "");
strcpy(filename, "");
SetWindowText(hwnd, "");
}
/*
open text for editing
*/
void DoOpen(HWND hwnd)
{
char *fname;
char *buff;
fname = GetOpenFile(hwnd);
if(!fname)
return;
buff = loadfile(fname);
if(!buff)
return;
SendMessage(GetDlgItem(hwnd, ID_TEXT_EDT), WM_SETTEXT, 0, (LPARAM) buff);
free(buff);
strcpy(filename, fname);
SetWindowText(hwnd, filename);
free(fname);
}
/*
Save text
*/
void DoSave(HWND hwnd)
{
HWND hedt;
int len;
char *buff;
if(!strlen(filename))
DoSaveAs(hwnd);
hedt = GetDlgItem(hwnd, ID_TEXT_EDT);
len = GetWindowTextLength(hedt);
buff = malloc(len + 100);
if(!buff)
return;
len = SendMessage(hedt, WM_GETTEXT, len, (LPARAM) buff);
buff[len] = 0;
savefile(filename, buff);
free(buff);
}
/*
save text to new file
*/
void DoSaveAs(HWND hwnd)
{
char *fname;
char *buff;
HWND hedt;
int ans;
int len;
fname = GetSaveFile(hwnd);
if(!fname)
return;
hedt = GetDlgItem(hwnd, ID_TEXT_EDT);
len = GetWindowTextLength(hedt);
buff = malloc(len + 100);
if(!buff)
return;
len = SendMessage(hedt, WM_GETTEXT, len, (LPARAM) buff);
buff[len] = 0;
ans = savefile(filename, buff);
free(buff);
if(ans == 0)
{
strcpy(filename, fname);
SetWindowText(hwnd, filename);
}
free(buff);
free(fname);
}
/*
get the name of a text file to open
*/
char *GetOpenFile(HWND hwnd)
{
OPENFILENAME ofn;
char path[MAX_PATH];
strcpy(path, " ");
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.hInstance = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE);
ofn.lpstrFilter = "Ascii files\0*.txt\0All files\0*.*\0\0";
ofn.lpstrCustomFilter = 0;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = path;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = 0;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = 0;
ofn.lpstrTitle = "Load Text file";
ofn.Flags = OFN_FILEMUSTEXIST;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt= "txt";
ofn.lCustData = 0;
ofn.lpfnHook = 0;
ofn.lpTemplateName = 0;
if( GetOpenFileName(&ofn) )
return mystrdup(path);
else
return 0;
}
/*
get name of text file to save to
*/
char *GetSaveFile(HWND hwnd)
{
OPENFILENAME ofn;
char path[MAX_PATH];
strcpy(path, "");
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.hInstance = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE);
ofn.lpstrFilter = "Ascii files\0*.txt\0All files\0*.*\0\0";
ofn.lpstrCustomFilter = 0;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = path;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = 0;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = 0;
ofn.lpstrTitle = "Save text file";
ofn.Flags = OFN_NOREADONLYRETURN;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt= "wld";
ofn.lCustData = 0;
ofn.lpfnHook = 0;
ofn.lpTemplateName = 0;
if( GetSaveFileName(&ofn) )
return mystrdup(path);
else
return 0;
}
/*
load a file
*/
static char *loadfile(char *path)
{
FILE *fp;
char *answer;
long len;
long i;
int ch;
fp = fopen(path, "r");
if(!fp)
return 0;
fseek(fp, 0, SEEK_END);
len = ftell(fp);
fseek(fp, 0, SEEK_SET);
answer = malloc(len * len/10 + 100);
if(!answer)
return 0;
while( (ch = fgetc(fp)) != EOF)
{
/* note Windows like carraige returns before newlines */
if(ch == '\n')
answer[i++] = '\r';
answer[i++] = ch;
}
answer
= 0;
fclose(fp);
return answer;
}
/*
save a file to disk
*/
static int savefile(char *path, char *str)
{
FILE *fp;
fp = fopen(path, "w");
if(!fp)
return -1;
if(fwrite(str, strlen(str), 1, fp) != 1)
{
fclose(fp);
return -1;
}
return fclose(fp);
}
/*
strdup
*/
static char *mystrdup(char *str)
{
char *answer;
answer = malloc(strlen(str) + 1);
strcpy(answer, str);
return answer;
}