#include #include #include #include #include #include #include "graphics.h" const char * const cppversion="graphics 1.03.015 of 24th June 2002"; #define debugbmp 0 struct HINSTANCE__ * MainInstance; char *CommandLine; const int keyboardinputlengthmax=1023; struct HINSTANCE__ * HNULL = (struct HINSTANCE__ *)NULL; char keyboardinput[1024]; int keyboardinputlength=0, newlinesinbuffer=0, keyboardmode=NORMAL_MODE; int mousedownx, mousedowny, mouseupx, mouseupy, mousebutton; int killed=0; char ClassName[32]="WFMICROSOFTSUCKSQKSHXNZKAKDISUW"; int __stdcall WindowProc(HWND, unsigned, unsigned, long); HANDLE awtevent, printmutex, semamutex, programthread; SECURITY_ATTRIBUTES secatt; HGDIOBJ blackpen=NULL; HBRUSH whitebrush=NULL; HFONT crappydefaultfont=NULL, ansifixedfont=NULL; int lastxpos=100; int threadcount=0; void main(void); int qwqwqwignorethis=0; jmp_buf exitplace; int time_zero=0, events_wanted=0; int defaultvisible=1; int thecount=0; int SMcxscreen, SMcyscreen; // screen width, height int SMcxfullscreen, SMcyfullscreen; // screen client area width, height int SMcycaption; // caption bar height int SMcxborder, SMcyborder; // window border width, height int SMcxicon, SMcyicon; // icon width, height int SMcxsmicon, SMcysmicon; // small icon width, height int SMcxsizeframe, SMcysizeframe; // window sizing frame width, height int SMcymenu; // menu bar height #define XMcreate (WM_USER+1) #define XMdestroy (WM_USER+2) #define XMmenu (WM_USER+20) #define XMmenu_exit (XMmenu+1) #define XMmenu_capture_text (XMmenu+2) #define XMmenu_capture_graphics (XMmenu+3) const int XMusermenumin=WM_USER+100; const int XMaddedmin=WM_USER+1000; const int NumHandlers=100; const int XMaddedmax=XMaddedmin+NumHandlers-1; int nexthandler=XMaddedmin; XFunction handlers[NumHandlers]; unsigned long int awteventthreadid, programthreadid; Xframe *mainframe=NULL; Xframe *textframe=NULL; const int logbuffersize=2000; FILE *logfile=NULL; char oldlog[logbuffersize]; void PrintLastError(char *where) { void *msgbuff; int k=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msgbuff, 0, NULL); printf("\nINTERNAL ERROR in %s:\n%s\n", where, msgbuff); LocalFree(msgbuff); } int CheckSameVersions(void) { int ok=(strcmp(hversion, cppversion)==0); if (ok) return 1; print("****************\n"); print("Versions Differ:\n"); print(" .h version is '"); print(hversion); print("'\n"); print(" .cpp version is '"); print(cppversion); print("'\n"); print("****************\n\n"); return 0; } int AddHandler(XFunction f) { if (nexthandler>XMaddedmax) return 0; int n=nexthandler; nexthandler+=1; handlers[n-XMaddedmin]=f; return n; } void defaulthandler(Xframe *fr, int msg, int param1, int param2) { } void log(char *patt, ...) { if (logfile==NULL) { logfile=fopen("log.log", "w"); fputs(oldlog, logfile); oldlog[0]=0; } va_list a; va_start(a, patt); vfprintf(logfile, patt, a); fflush(logfile); } void ilog(char *patt, ...) { va_list a; va_start(a, patt); if (logfile==NULL) { int oldlen=strlen(oldlog); int space=logbuffersize-oldlen-2; int npr=_vsnprintf(oldlog+oldlen, space, patt, a); if (npr>=0) return; oldlog[oldlen]=0; logfile=fopen("log.log", "w"); fputs(oldlog, logfile); oldlog[0]=0; } vfprintf(logfile, patt, a); fflush(logfile); } void SetLogFile(char *fn) { if (logfile!=NULL) fclose(logfile); logfile=fopen(fn, "w"); fputs(oldlog, logfile); oldlog[0]=0; } RECT *make_rect_xywh(int x, int y, int w, int h) { static RECT r; r.left=x; r.top=y; r.right=x+w; r.bottom=y+h; return (&r); } RECT *make_rect_xyxy(int x, int y, int x1, int y1) { static RECT r; r.left=x; r.top=y; r.right=x1; r.bottom=y1; return (&r); } void settext(char *d, char *s) { for (int i=0; 1; i+=1) { char c=s[i]; if (c==0) break; d[i]=c; } } void TextOutput::setcontainer(Xframe *f) { container=f; } HDC Xframe::getDC(void) { return hdc; } void Xframe::setDC(HDC h) { hdc=h; } HDC Xframe::getpaintDC(void) { return paintdc; } void Xframe::setpaintDC(HDC h) { paintdc=h; } HWND Xframe::getHWND(void) { return hwnd; } int Xframe::istext(void) { return tout!=NULL; } TextOutput *Xframe::gettext(void) { return tout; } void TextOutput::get(int &ht, int &wd, char ** &data) { ht=textbufferlines; wd=textlinewidth; data=textbuffer; } TextOutput::TextOutput(int ht, int wd) { textbufferlines=ht; textbuffer=new char *[ht]; for (int i=0; iSetCaption(s); } void TextOutput::print_flush(void) { if (container==NULL) return; container->repaint(); changed=0; } void TextOutput::savein(FILE *f) { if (textbuffer==NULL) return; for (int i=0; i<=currentlinenum; i+=1) { int end=textlinewidth-1; char *thisline=textbuffer[i]; while (end>=0 && thisline[end]==' ') end-=1; for (int j=0; j<=end; j+=1) fputc(thisline[j], f); fputc('\n', f); } } void TextOutput::print_char(char c) { if (textbuffer==NULL) return; if (currentcharpos>=textlinewidth || c=='\n') { if (currentlinenum>=textbufferlines-1) { char *line0=textbuffer[0]; for (int i=0; irepaint(); changed=0; } if (c=='\n') return; changed=1; currentline[currentcharpos]=c; currentcharpos+=1; } int TextOutput::cursor_position(void) { return currentcharpos; } void TextOutput::print_string(const char *s) { for (int i=0; 1; i+=1) { char c=s[i]; if (c==0) break; print_char(c); } } void TextOutput::print_int(int n) { char b[100]; if (n<0) { print_char('-'); n=-n; } int len=0; while (1) { b[len]='0'+n%10; n=n/10; len+=1; if (n==0) break; } for (int i=len-1; i>=0; i-=1) print_char(b[i]); } void TextOutput::print_hex(int n) { int pd=0; for (int i=28; i>=0; i-=1) { int d=(n>>i) & 0xf; if (d!=0 || i==0) pd=1; if (pd) { if (d>9) print_char('A'+d-10); else print_char('0'+d); } } } int TextOutput::vaprintf(char *patt, va_list &a) { DWORD r=WaitForSingleObjectEx(printmutex,INFINITE,0); if (r!=WAIT_OBJECT_0) return 0; char buff[1002]; _vsnprintf(buff, 1000, patt, a); print_string(buff); va_end(a); ReleaseMutex(printmutex); if (changed && container!=NULL) container->repaint(); changed=0; return 1; } int TextOutput::printf(char *patt, ...) { va_list a; va_start(a, patt); return vaprintf(patt, a); } TextOutput *text=NULL; void SetConsoleCaption(char *s) { if (text==NULL) return; text->SetCaption(s); } void print_char(char c) { if (text==NULL) return; text->print_char(c); text->print_flush(); } void print_int(int n) { if (text==NULL) return; text->print_int(n); text->print_flush(); } void print_string(const char *n) { if (text==NULL) return; text->print_string(n); text->print_flush(); } void printf(char *patt, ...) { if (text==NULL) return; va_list a; va_start(a, patt); text->vaprintf(patt, a); text->print_flush(); } void print_hex(int n) { if (text==NULL) return; text->print_hex(n); } int get_text_cursor_position(void) { if (text==NULL) return 0; return text->cursor_position(); } void print_flush(void) { if (text==NULL) return; text->print_flush(); } char *safestring(const char *s) { char *r=new char[strlen(s)+1]; strcpy(r,s); return r; } struct EventRecord { int e, x, y, t, c; Xframe *f; }; const int maxevents = 1000; EventRecord eventlist[maxevents]; int firstevent=0, lastevent=maxevents-1, numevents=0; void CaptureEvents(int ee) { events_wanted |= ee; } void IgnoreEvents(int ee) { events_wanted &= ~ee; } int GetNextEvent(int &e, int &x, int &y, int &t, int &c, Xframe *&f) { if (numevents<=0) { e=0; x=0; y=0; t=0; c=0; f=NULL; return 0; } EventRecord er=eventlist[firstevent]; firstevent+=1; if (firstevent>=maxevents) firstevent=0; numevents-=1; if (numevents<=0) { firstevent=0; lastevent=maxevents-1; numevents=0; } e=er.e; x=er.x; y=er.y; t=er.t; c=er.c; f=er.f; return 1; } int GetNextEvent(int &e, int &x, int &y, int &t, int &c) { Xframe *f; return GetNextEvent(e, x, y, t, c, f); } int WaitAndGetNextEvent(int &e, int &x, int &y, int &t, int &c, Xframe *&f) { while (numevents==0) Sleep(25); EventRecord er=eventlist[firstevent]; firstevent+=1; if (firstevent>=maxevents) firstevent=0; numevents-=1; if (numevents<=0) { firstevent=0; lastevent=maxevents-1; numevents=0; } e=er.e; x=er.x; y=er.y; t=er.t; c=er.c; f=er.f; return 1; } int WaitAndGetNextEvent(int &e, int &x, int &y, int &t, int &c) { Xframe *f; return WaitAndGetNextEvent(e, x, y, t, c, f); } int LimitedWaitAndGetNextEvent(double timeout, int &e, int &x, int &y, int &t, int &c, Xframe *&f) { int to=(int)(0.5+timeout*1000.0); while (numevents==0 && to>0) { Sleep(25); to-=25; } if (numevents<=0) { e=0; x=0; y=0; t=0; c=0; f=NULL; return 0; } EventRecord er=eventlist[firstevent]; firstevent+=1; if (firstevent>=maxevents) firstevent=0; numevents-=1; if (numevents<=0) { firstevent=0; lastevent=maxevents-1; numevents=0; } e=er.e; x=er.x; y=er.y; t=er.t; c=er.c; f=er.f; return 1; } int LimitedWaitAndGetNextEvent(double timeout, int &e, int &x, int &y, int &t, int &c) { Xframe *f; return LimitedWaitAndGetNextEvent(timeout, e, x, y, t, c, f); } int register_event(int e, int x, int y, Xframe *f, int cause=0) { if (numevents>=maxevents) return 0; EventRecord er; er.e=e; er.x=x; er.y=y; er.c=cause; er.f=f; struct _timeb timebuffer; _ftime(&timebuffer); er.t=(timebuffer.time-time_zero)*1000+timebuffer.millitm; lastevent+=1; if (lastevent>=maxevents) lastevent=0; eventlist[lastevent]=er; numevents+=1; return 1; } string GetEventName(int e) { char buffer[1000]; buffer[0]=0; int mask=1; for (int i=1; i=1 && c<=26) { strcpy(tmp, "CONTROL+' '"); tmp[9]=c+64; return tmp; } else if (c>32 && c<127) { strcpy(tmp, "' '"); tmp[1]=c; return tmp; } else { sprintf(tmp, "ASCII+%d", c); return tmp; } } int Xframe::nxtnum=0; int Xframe::numframes=0; int Xframe::defaultmode=AUTOMATIC_MODE; void Xframe::SetDefaultWindowMode(int m) { defaultmode=m; } void SetDefaultWindowMode(int m) { Xframe::SetDefaultWindowMode(m); } int Xframe::getmode(void) { return mode; } int Xframe::HasMenuBar(void) { if (tout!=NULL) return 1; if (menus!=NULL) return 1; return 0; } void painttextplease(Xframe *fr); void autopaint(Xframe *fr); // -1 -1 NULL -999888 -999888 1 remove Xframe::Xframe(int wp, int hp, char *tt, int xp, int yp, int vis, TextOutput *to) { char capt[256]; tout=to; if (tout==NULL) { mode=AUTOMATIC_MODE; mainframe=this; } else { tout->setcontainer(this); mode=REDRAW_MODE; } hwnd=NULL; painter=NULL; bitmap=NULL; bitmapdc=NULL; paintdc=NULL; nxtnum+=1; mynum=nxtnum; numframes+=1; gotmetrics=0; repainthappening=0; isminimal=0; ismaximal=0; batching=0; menus=NULL; menubar=NULL; drawingmutex=CreateMutex(NULL,0,NULL); fontface=0; fontattr=0; fontsize=0; strcpy(fontname,""); fontchanged=0; if (tt==NULL) _snprintf(capt, 254, "#%d: %s", mynum, cppversion); else _snprintf(capt, 254, "#%d: %s", mynum, tt); title=safestring(capt); if (xp==-999888) xpos=nxtnum*40; else xpos=xp; if (yp==-999888) ypos=nxtnum*40; else ypos=yp; if (wp==-1) width=200; else width=wp; if (hp==-1) height=200; else height=hp; hreg=CreateRectRgn(0,0,width,height); hregb=CreateRectRgn(0,0,width,height); ongoingw=width; ongoingh=height; create(tout==NULL ? NULL : painttextplease); if (vis) appear(); } void Xframe::SetObject(void *o) { object=o; } void *Xframe::GetObject(void) { return object; } void MakeLogfont(LOGFONT &lf) { int n=sizeof LOGFONT; char *p=(char *)&lf; for (int j=0; jbitmaph || desw>bitmapw) { HBITMAP newbitmap=CreateCompatibleBitmap(bitmapdc, desw, desh); HDC newbitmapdc=CreateCompatibleDC(bitmapdc); SelectObject(newbitmapdc, newbitmap); FillRect(newbitmapdc, make_rect_xyxy(0,0,desw,desh), whitebrush); BitBlt(newbitmapdc, 0, 0, bitmapw, bitmaph, bitmapdc, 0, 0, SRCCOPY); DeleteDC(newbitmapdc); SelectObject(bitmapdc, newbitmap); DeleteObject(bitmap); bitmap=newbitmap; bitmapw=desw; bitmaph=desh; } InvalidateRect(hwnd,NULL,0); } width=ongoingw; height=ongoingh; } void Xframe::threadedcreate(void) { int dw=2*SMcxsizeframe, dh=SMcycaption+2*SMcysizeframe; if (tout!=NULL) dh+=SMcymenu; hwnd=CreateWindow(ClassName,title,WS_OVERLAPPEDWINDOW,xpos,ypos,width+dw,height+dh,NULL,NULL,MainInstance,NULL); if (hwnd==NULL) { log("**** Xframe::threadedcreate CreateWindow FAILED\n"); return; } SetWindowLong(hwnd, GWL_USERDATA, (long)this); SetEvent(awtevent); ReobtainDC(); if (tout!=NULL) { HMENU menubar=CreateMenu(); HMENU menu=CreatePopupMenu(); AppendMenu(menu, MF_STRING, XMmenu_exit, "Exit"); AppendMenu(menubar, MF_POPUP, (int)menu, "File"); menu=CreatePopupMenu(); AppendMenu(menu, MF_STRING, XMmenu_capture_text, "Capture Console Text"); AppendMenu(menu, MF_STRING, XMmenu_capture_graphics, "Capture Graphics"); AppendMenu(menubar, MF_POPUP, (int)menu, "Capture"); SetMenu(hwnd, menubar); DrawMenuBar(hwnd); } } void Xframe::Close(void) { if (hwnd==NULL) return; PostThreadMessage(awteventthreadid, XMdestroy, 0, (long)this); } void Xframe::dispose(void) { if (hwnd==NULL) return; ReleaseDC(); hwnd=NULL; numframes-=1; if (numframes<=0) ExitThread(1); } void Xframe::appear(void) { if (hwnd==NULL) return; InvalidateRect(hwnd,NULL,0); ShowWindow(hwnd, SW_SHOWDEFAULT); } void Xframe::repaint(void) { if (hwnd==NULL) return; InvalidateRect(hwnd,NULL,0); } void FirstInstance(void) { WNDCLASS wc; int rc; wc.style=CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc=(WNDPROC)WindowProc; wc.cbClsExtra=0; wc.cbWndExtra=sizeof(DWORD); wc.hInstance=MainInstance; wc.hIcon=LoadIcon(MainInstance, "MainIcon"); wc.hCursor=LoadCursor(NULL, IDC_ARROW); wc.hbrBackground=(struct HBRUSH__ *)GetStockObject(WHITE_BRUSH); wc.lpszMenuName=NULL; wc.lpszClassName=ClassName; rc=RegisterClass(&wc); if (rc==0) { log("FirstInstance Failed to register class \"%s\", ExitProcess\n",ClassName); ExitProcess(1); } } void MakeWindow(int w, int h, int xtl /* =-999888 */, int ytl /* =-999888 */) { mainframe=new Xframe(w, h, NULL, xtl, ytl, 1, NULL); } void SetDefaultWindowVisibility(int v) { defaultvisible=v; } void DefaultMake(void) { if (defaultvisible) mainframe=new Xframe(SMcxfullscreen-20, SMcyfullscreen-70, NULL, 10, 10, 1, NULL); else mainframe=new Xframe(70, 30, NULL, 10, 10, 0, NULL); } int Xframe::SendEvent(int e, int x, int y, int cause) { if (events_wanted &e) return register_event(e, x, y, this, cause); return 0; } int SendEvent(int e, int x, int y, int cause) { if (events_wanted &e) return register_event(e, x, y, mainframe, cause); return 0; } void Xframe::internallysetsize(int w, int h) { width=w; height=h; } void Xframe::internallysetpos(int x, int y) { xpos=x; ypos=y; } void Xframe::SetSize(int w, int h) { RECT r; GetWindowRect(hwnd, &r); ongoingw=w; ongoingh=h; resizetoongoing(); int dw=2*SMcxsizeframe, dh=SMcycaption+2*SMcysizeframe; if (tout!=NULL || menubar!=NULL) dh+=SMcymenu; MoveWindow(hwnd, r.left, r.top, w+dw, h+dh, 1); if (mode==AUTOMATIC_MODE && (events_wanted & WINDOW_RESIZED)) register_event(WINDOW_RESIZED, w, h, this, 1); } void Xframe::SetSize(Region r) { SetSize(r.right-r.left, r.bottom-r.top); } void SetSize(int w, int h) { if (mainframe==NULL) DefaultMake(); mainframe->SetSize(w,h); } void SetSize(Region r) { if (mainframe==NULL) DefaultMake(); mainframe->SetSize(r); } void Xframe::SetLocation(Region r) { int w=r.right-r.left, h=r.bottom-r.top; ongoingw=w; ongoingh=h; resizetoongoing(); int dw=2*SMcxsizeframe, dh=SMcycaption+2*SMcysizeframe; if (tout!=NULL || menubar!=NULL) dh+=SMcymenu; MoveWindow(hwnd, r.left, r.top, w+dw, h+dh, 1); if (mode==AUTOMATIC_MODE && (events_wanted & WINDOW_RESIZED)) register_event(WINDOW_RESIZED, w, h, this, 1); } void SetLocation(Region r) { if (mainframe==NULL) DefaultMake(); mainframe->SetLocation(r); } int Xframe::GetIndexNumber(void) { return mynum; } void Xframe::SetCaption(char *s) { char capt[256]; _snprintf(capt, 250, "#%d: %s", mynum, s); SetWindowText(hwnd, capt); } void Xframe::SetCaption(string s) { SetCaption(s.getcstr()); } void SetCaption(char *s) { if (mainframe==NULL) DefaultMake(); mainframe->SetCaption(s); } void SetCaption(string s) { if (mainframe==NULL) DefaultMake(); mainframe->SetCaption(s); } Region MakeRegionXYXY(int x, int y, int x1, int y1) { Region r; r.left=x; r.top=y; r.right=x1; r.bottom=y1; return r; } Region MakeRegionXYWH(int x, int y, int w, int h) { Region r; r.left=x; r.top=y; r.right=x+w; r.bottom=y+h; return r; } Region MakeRegionXY(int x, int y) { Region r; r.left=x; r.top=y; r.right=-999888; r.bottom=-999888; return r; } Region MakeRegionWH(int w, int h) { Region r; r.left=-999888; r.top=-999888; r.right=w-999888; r.bottom=h-999888; return r; } void Xframe::GetSize(Region &r) { r.top=0; r.left=0; r.right=width; r.bottom=height; } void Xframe::GetLocation(Region &r) { r.top=ypos; r.left=xpos; r.right=xpos+width; r.bottom=ypos+height; } void GetLocation(Region &r) { if (mainframe==NULL) DefaultMake(); mainframe->GetLocation(r); } Region Xframe::GetLocation(void) { Region r; r.top=ypos; r.left=xpos; r.right=xpos+width; r.bottom=ypos+height; return r; } Region GetLocation(void) { if (mainframe==NULL) DefaultMake(); return mainframe->GetLocation(); } void Xframe::GetSize(int &w, int &h) { w=width; h=height; } int firstfreemenu=XMusermenumin; menulist::menulist(HMENU m, char *n) { menu=m; name=safestring(n); next=NULL; } void Xframe::AddMenuBar(void) { int resize=menubar==NULL; menubar=CreateMenu(); SetMenu(hwnd, menubar); DrawMenuBar(hwnd); if (resize) { RECT r; GetWindowRect(hwnd, &r); MoveWindow(hwnd, r.left, r.top, r.right-r.left, r.bottom-r.top+SMcymenu, 1); } menus=NULL; } void AddMenuBar(void) { if (mainframe==NULL) DefaultMake(); mainframe->AddMenuBar(); } HMENU Xframe::AddMenu(string nm) { if (menubar==NULL) AddMenuBar(); char *name=nm.getcstr(); HMENU menu=CreatePopupMenu(); AppendMenu(menubar, MF_POPUP, (int)menu, name); menulist *ml=new menulist(menu, name); ml->next=menus; menus=ml; DrawMenuBar(hwnd); return menu; } void AddMenu(string nm) { if (mainframe==NULL) DefaultMake(); mainframe->AddMenu(nm); } HMENU Xframe::findmenu(char *name) { menulist *ml=menus; while (ml!=NULL) { if (strcmp(ml->name, name)==0) break; ml=ml->next; } if (ml==NULL) return AddMenu(name); else return ml->menu; } int Xframe::AddMenuItem(string mnm, string nm, int code) { HMENU menu=findmenu(mnm.getcstr()); AppendMenu(menu, MF_STRING, code, nm.getcstr()); DrawMenuBar(hwnd); return code; } int Xframe::AddMenuItem(string mnm, string nm) { firstfreemenu+=1; int code=firstfreemenu; return AddMenuItem(mnm, nm, code); } int AddMenuItem(string mnm, string nm, int code) { if (mainframe==NULL) DefaultMake(); return mainframe->AddMenuItem(mnm, nm, code); } int AddMenuItem(string mnm, string nm) { if (mainframe==NULL) DefaultMake(); return mainframe->AddMenuItem(mnm, nm); } void CloseWindow(void) { if (mainframe==NULL) return; mainframe->Close(); } void GetSize(int &w, int &h) { if (mainframe==NULL) DefaultMake(); mainframe->GetSize(w, h); } void GetSize(Region &r) { if (mainframe==NULL) DefaultMake(); mainframe->GetSize(r); } void Xframe::RestrictDrawingTo(Region r) { SetRectRgn(hreg, r.left, r.top, r.right, r.bottom); SetRectRgn(hregb, r.left, r.top, r.right, r.bottom); SelectClipRgn(bitmapdc, hregb); if (mode==AUTOMATIC_MODE) { start(); SelectClipRgn(hdc, hreg); stop(); } } void RestrictDrawingTo(Region r) { if (mainframe==NULL) DefaultMake(); mainframe->RestrictDrawingTo(r); } void Xframe::UnrestrictedDrawing(void) { SelectClipRgn(bitmapdc, NULL); if (mode==AUTOMATIC_MODE) { start(); SelectClipRgn(hdc, NULL); stop(); } } void UnrestrictedDrawing(void) { if (mainframe==NULL) DefaultMake(); mainframe->UnrestrictedDrawing(); } void Xframe::setHeading(double dx, double dy) { heading=atan2(dx, -dy); if (dx==0) { if (dy<=0) headingminutes=0; else headingminutes=10800; } else if (dy==0) { if (dx<0) headingminutes=16200; else headingminutes=5400; } else headingminutes=-1; } int number_of_timers=100; int Xframe::StartRegularTimer(double period) { number_of_timers+=2; return SetTimer(hwnd, number_of_timers, (int)(0.5+1000.0*period), NULL); } int StartRegularTimer(double period) { if (mainframe==NULL) DefaultMake(); return mainframe->StartRegularTimer(period); } int Xframe::StartSingleTimer(double howlong) { number_of_timers+=2; return SetTimer(hwnd, number_of_timers+1, (int)(0.5+1000.0*howlong), NULL); } int StartSingleTimer(double howlong) { if (mainframe==NULL) DefaultMake(); return mainframe->StartSingleTimer(howlong); } void Xframe::MoveTo(double x, double y) { setHeading(x-penx, peny-y); penx=x; peny=y; MoveToEx(bitmapdc, (int)penx, (int)peny, NULL); if (mode==AUTOMATIC_MODE) { start(); MoveToEx(hdc, (int)penx, (int)peny, NULL); stop(); } } void MoveTo(double x, double y) { if (mainframe==NULL) DefaultMake(); mainframe->MoveTo(x, y); } void Xframe::MoveByLength(double s) { penx=penx+s*sin(heading); peny=peny-s*cos(heading); MoveToEx(bitmapdc, (int)penx, (int)peny, NULL); if (mode==AUTOMATIC_MODE) { start(); MoveToEx(hdc, (int)penx, (int)peny, NULL); stop(); } } void MoveByLength(double s) { if (mainframe==NULL) DefaultMake(); mainframe->MoveByLength(s); } void Xframe::MoveBy(double dx, double dy) { setHeading(dx, dy); penx+=dx; peny+=dy; MoveToEx(bitmapdc, (int)penx, (int)peny, NULL); if (mode==AUTOMATIC_MODE) { start(); MoveToEx(hdc, (int)penx, (int)peny, NULL); stop(); } } void MoveBy(double dx, double dy) { if (mainframe==NULL) DefaultMake(); mainframe->MoveBy(dx, dy); } int Xframe::GetPixelColor(int x, int y) { int c=GetPixel(bitmapdc, x, y); if (c==CLR_INVALID) c=0; return c; } int GetPixelColor(int x, int y) { if (mainframe==NULL) DefaultMake(); return mainframe->GetPixelColor(x, y); } void Xframe::GetPixelColor0255(int x, int y, int &r, int &g, int &b) { int c=GetPixel(bitmapdc, x, y); if (c==CLR_INVALID) c=0; r=c&255; g=(c>>8)&255; b=(c>>16)&255; } void GetPixelColor0255(int x, int y, int &r, int &g, int &b) { if (mainframe==NULL) DefaultMake(); mainframe->GetPixelColor0255(x, y, r, g, b); } void Xframe::GetPixelColor(int x, int y, float &r, float &g, float &b) { int c=GetPixel(bitmapdc, x, y); if (c==CLR_INVALID) c=0; r=(float)((c&255)/255.0); g=(float)(((c>>8)&255)/255.0); b=(float)(((c>>16)&255)/255.0); } void GetPixelColor(int x, int y, float &r, float &g, float &b) { if (mainframe==NULL) DefaultMake(); mainframe->GetPixelColor(x, y, r, g, b); } void Xframe::GetPixelColor(int x, int y, double &r, double &g, double &b) { int c=GetPixel(bitmapdc, x, y); if (c==CLR_INVALID) c=0; r=(c&255)/255.0; g=((c>>8)&255)/255.0; b=((c>>16)&255)/255.0; } void GetPixelColor(int x, int y, double &r, double &g, double &b) { if (mainframe==NULL) DefaultMake(); mainframe->GetPixelColor(x, y, r, g, b); } void Xframe::DrawPointAt(double x, double y) { MoveTo(x, y); LineTo(bitmapdc, (int)x, (int)y); if (mode==AUTOMATIC_MODE) { start(); LineTo(hdc, (int)x, (int)y); stop(); } } void DrawPointAt(double x, double y) { if (mainframe==NULL) DefaultMake(); mainframe->DrawPointAt(x, y); } void Xframe::DrawPointHere(void) { LineTo(bitmapdc, (int)penx, (int)peny); if (mode==AUTOMATIC_MODE) { start(); LineTo(hdc, (int)penx, (int)peny); stop(); } } void DrawPointHere(void) { if (mainframe==NULL) DefaultMake(); mainframe->DrawPointHere(); } void Xframe::ColorPixel0255(int x, int y, int R, int G, int B) { SetPixel(bitmapdc, x, y, (B<<16)|(G<<8)|(R)); if (mode==AUTOMATIC_MODE) { start(); SetPixel(hdc, x, y, (B<<16)|(G<<8)|(R)); stop(); } } void ColorPixel0255(int x, int y, int R, int G, int B) { if (mainframe==NULL) DefaultMake(); mainframe->ColorPixel0255(x, y, R, G, B); } void Xframe::ColorPixel(int x, int y, int c) { SetPixel(bitmapdc, x, y, c); if (mode==AUTOMATIC_MODE) { start(); SetPixel(hdc, x, y, c); stop(); } } void ColorPixel(int x, int y, int c) { if (mainframe==NULL) DefaultMake(); mainframe->ColorPixel(x, y, c); } void Xframe::ColorPixel(int x, int y, double R, double G, double B) { int r=(int)(R*255.0+0.5); int g=(int)(G*255.0+0.5); int b=(int)(B*255.0+0.5); SetPixel(bitmapdc, x, y, (b<<16)|(g<<8)|(r)); if (mode==AUTOMATIC_MODE) { start(); SetPixel(hdc, x, y, (b<<16)|(g<<8)|(r)); stop(); } } void ColorPixel(int x, int y, double R, double G, double B) { if (mainframe==NULL) DefaultMake(); mainframe->ColorPixel(x, y, R, G, B); } void Xframe::DrawLineTo(double x, double y) { LineTo(bitmapdc, (int)x, (int)y); if (mode==AUTOMATIC_MODE) { start(); LineTo(hdc, (int)x, (int)y); stop(); } setHeading(x-penx, peny-y); penx=x; peny=y; } void DrawLineTo(double x, double y) { if (mainframe==NULL) DefaultMake(); mainframe->DrawLineTo(x, y); } void Xframe::DrawLineLength(double s) { double newx=penx+s*sin(heading); double newy=peny-s*cos(heading); LineTo(bitmapdc, (int)(0.5+newx), (int)(0.5+newy)); if (mode==AUTOMATIC_MODE) { start(); LineTo(hdc, (int)(0.5+newx), (int)(0.5+newy)); stop(); } penx=newx; peny=newy; } void DrawLineLength(double s) { if (mainframe==NULL) DefaultMake(); mainframe->DrawLineLength(s); } void Xframe::DrawLineBy(double dx, double dy) { LineTo(bitmapdc, (int)(penx+dx), (int)(peny+dy)); if (mode==AUTOMATIC_MODE) { start(); LineTo(hdc, (int)(penx+dx), (int)(peny+dy)); stop(); } setHeading(dx, -dy); penx+=dx; peny+=dy; } void DrawLineBy(double dx, double dy) { if (mainframe==NULL) DefaultMake(); mainframe->DrawLineBy(dx, dy); } void Xframe::DrawRectangleXYXY(double x0, double y0, double x1, double y1) { MoveToEx(bitmapdc, (int)x0, (int)y0, NULL); LineTo(bitmapdc, (int)x1, (int)y0); LineTo(bitmapdc, (int)x1, (int)y1); LineTo(bitmapdc, (int)x0, (int)y1); LineTo(bitmapdc, (int)x0, (int)y0); MoveToEx(bitmapdc, (int)penx, (int)peny, NULL); if (mode==AUTOMATIC_MODE) { start(); MoveToEx(hdc, (int)x0, (int)y0, NULL); LineTo(hdc, (int)x1, (int)y0); LineTo(hdc, (int)x1, (int)y1); LineTo(hdc, (int)x0, (int)y1); LineTo(hdc, (int)x0, (int)y0); MoveToEx(hdc, (int)penx, (int)peny, NULL); stop(); } } void DrawRectangleXYXY(double x0, double y0, double x1, double y1) { if (mainframe==NULL) DefaultMake(); mainframe->DrawRectangleXYXY(x0, y0, x1, y1); } void Xframe::DrawRectangleXYWH(double x0, double y0, double w, double h) { int x1=(int)(x0+w-1), y1=(int)(y0+h-1); MoveToEx(bitmapdc, (int)x0, (int)y0, NULL); LineTo(bitmapdc, x1, (int)y0); LineTo(bitmapdc, x1, y1); LineTo(bitmapdc, (int)x0, y1); LineTo(bitmapdc, (int)x0, (int)y0); MoveToEx(bitmapdc, (int)penx, (int)peny, NULL); if (mode==AUTOMATIC_MODE) { start(); MoveToEx(hdc, (int)x0, (int)y0, NULL); LineTo(hdc, x1, (int)y0); LineTo(hdc, x1, y1); LineTo(hdc, (int)x0, y1); LineTo(hdc, (int)x0, (int)y0); MoveToEx(hdc, (int)penx, (int)peny, NULL); stop(); } } void DrawRectangleXYWH(double x0, double y0, double w, double h) { if (mainframe==NULL) DefaultMake(); mainframe->DrawRectangleXYWH(x0, y0, w, h); } void Xframe::DrawRectangle(Region r) { DrawRectangleXYXY(r.left, r.top, r.right, r.bottom); } void DrawRectangle(Region r) { if (mainframe==NULL) DefaultMake(); mainframe->DrawRectangle(r); } void Xframe::FillRectangleXYXY(double x0, double y0, double x1, double y1) { if (brushrgb!=penrgb) { if (currentbrush!=whitebrush) { DeleteObject(currentbrush); currentbrush=whitebrush; } brushrgb=penrgb; if (brushrgb!=0xFFFFFF00) currentbrush=CreateSolidBrush(brushrgb); } FillRect(bitmapdc, make_rect_xyxy((int)x0, (int)y0, (int)(x1+1), (int)(y1+1)), currentbrush); if (mode==AUTOMATIC_MODE) { start(); FillRect(hdc, make_rect_xyxy((int)x0, (int)y0, (int)(x1+1), (int)(y1+1)), currentbrush); stop(); } } void FillRectangleXYXY(double x0, double y0, double x1, double y1) { if (mainframe==NULL) DefaultMake(); mainframe->FillRectangleXYXY(x0, y0, x1, y1); } void Xframe::FillRectangleXYWH(double x0, double y0, double w, double h) { FillRectangleXYXY(x0, y0, x0+w-1, y0+h-1); } void FillRectangleXYWH(double x0, double y0, double w, double h) { if (mainframe==NULL) DefaultMake(); mainframe->FillRectangleXYWH(x0, y0, w, h); } void Xframe::FillRectangle(Region r) { FillRectangleXYXY(r.left, r.top, r.right, r.bottom); } void FillRectangle(Region r) { if (mainframe==NULL) DefaultMake(); mainframe->FillRectangle(r); } void Xframe::TurnLeftBy(double r) { headingminutes=-1; heading-=r; int n=(int)(heading/6.283185307179586476925286766559); heading-=n*6.283185307179586476925286766559; if (heading<0.0) heading+=6.283185307179586476925286766559; } void TurnLeftBy(double r) { if (mainframe==NULL) DefaultMake(); mainframe->TurnLeftBy(r); } void Xframe::TurnLeftByDegrees(double d) { if (d<0 || d>=360) { int n=(int)(d/360); d-=n*360; if (d<0) d+=360; } if (headingminutes<0) headingminutes=(int)(0.5+heading*180.0*60.0/3.1415926535897932384626433832795); headingminutes-=(int)(0.5+d*60); if (headingminutes<0) headingminutes+=21600; heading=headingminutes/21600.0*6.283185307179586476925286766559; } void TurnLeftByDegrees(double d) { if (mainframe==NULL) DefaultMake(); mainframe->TurnLeftByDegrees(d); } void Xframe::TurnRightBy(double r) { headingminutes=-1; heading+=r; int n=(int)(heading/6.283185307179586476925286766559); heading-=n*6.283185307179586476925286766559; if (heading<0.0) heading+=6.283185307179586476925286766559; } void TurnRightBy(double r) { if (mainframe==NULL) DefaultMake(); mainframe->TurnRightBy(r); } void Xframe::TurnRightByDegrees(double d) { if (d<0 || d>=360) { int n=(int)(d/360); d-=n*360; if (d<0) d+=360; } if (headingminutes<0) headingminutes=(int)(0.5+heading*180.0*60.0/3.1415926535897932384626433832795); headingminutes+=(int)(0.5+d*60); if (headingminutes>=21600) headingminutes-=21600; heading=headingminutes/21600.0*6.283185307179586476925286766559; } void TurnRightByDegrees(double d) { if (mainframe==NULL) DefaultMake(); mainframe->TurnRightByDegrees(d); } void Xframe::TurnToHeading(double r) { headingminutes=-1; heading=r; int n=(int)(heading/6.283185307179586476925286766559); heading-=n*6.283185307179586476925286766559; if (heading<0.0) heading+=6.283185307179586476925286766559; } void TurnToHeading(double r) { if (mainframe==NULL) DefaultMake(); mainframe->TurnToHeading(r); } void Xframe::TurnToHeadingDegrees(double d) { if (d<0 || d>=360) { int n=(int)(d/360); d-=n*360; if (d<0) d+=360; } headingminutes=(int)(0.5+60*d); heading=headingminutes/21600.0*6.283185307179586476925286766559; } void TurnToHeadingDegrees(double d) { if (mainframe==NULL) DefaultMake(); mainframe->TurnToHeadingDegrees(d); } double Xframe::DirectionTo(double x, double y) { return atan2(x-penx, peny-y); } double DirectionTo(double x, double y) { if (mainframe==NULL) DefaultMake(); return mainframe->DirectionTo(x,y); } double DirectionFromTo(double x0, double y0, double x1, double y1) { return atan2(x1-x0, y0-y1); } double Xframe::DirectionToDegrees(double x, double y) { return atan2(x-penx, peny-y)*360.0/6.283185307179586476925286766559; } double DirectionToDegrees(double x, double y) { if (mainframe==NULL) DefaultMake(); return mainframe->DirectionToDegrees(x,y); } double DirectionFromToDegrees(double x0, double y0, double x1, double y1) { return atan2(x1-x0, y0-y1)*360.0/6.283185307179586476925286766559; } double Xframe::DistanceTo(double x, double y) { return sqrt((penx-x)*(penx-x)+(peny-y)*(peny-y)); } double DistanceTo(double x, double y) { if (mainframe==NULL) DefaultMake(); return mainframe->DistanceTo(x,y); } double DistanceFromTo(double x0, double y0, double x1, double y1) { return sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1)); } void Xframe::GetPosition(int &x, int &y) { x=(int)penx; y=(int)peny; } void GetPosition(int &x, int &y) { if (mainframe==NULL) DefaultMake(); mainframe->GetPosition(x, y); } void Xframe::GetPosition(float &x, float &y) { x=(float)penx; y=(float)peny; } void GetPosition(float &x, float &y) { if (mainframe==NULL) DefaultMake(); mainframe->GetPosition(x, y); } void Xframe::GetPosition(double &x, double &y) { x=penx; y=peny; } void GetPosition(double &x, double &y) { if (mainframe==NULL) DefaultMake(); mainframe->GetPosition(x, y); } double Xframe::GetHeading(void) { int n=(int)(heading/6.283185307179586476925286766559); heading-=n*6.283185307179586476925286766559; if (heading<0.0) heading+=6.283185307179586476925286766559; return heading; } double GetHeading(void) { if (mainframe==NULL) DefaultMake(); return mainframe->GetHeading(); } double Xframe::GetHeadingDegrees(void) { if (headingminutes>=0) return headingminutes/60.0; int n=(int)(heading/6.283185307179586476925286766559); heading-=n*6.283185307179586476925286766559; if (heading<0.0) heading+=6.283185307179586476925286766559; return heading*360.0/6.283185307179586476925286766559; } double GetHeadingDegrees(void) { if (mainframe==NULL) DefaultMake(); return mainframe->GetHeadingDegrees(); } void Xframe::SetFontFace(int ff, char *fn) { if (ff==FONT_NAMED) { if (fontface!=FONT_NAMED || strcmp(fn, fontname)!=0) fontchanged=1; strncpy(fontname, fn, 90); } else { if (fontface!=ff) fontchanged=1; strcpy(fontname, ""); } fontface=ff; } void Xframe::SetFontFace(char *fn) { if (fontface!=FONT_NAMED || strcmp(fn, fontname)!=0) fontchanged=1; strncpy(fontname, fn, 90); fontface=FONT_NAMED; } void Xframe::SetFontFace(string fn) { SetFontFace(FONT_NAMED, fn.getcstr()); } void Xframe::SetFontAttributes(int fa) { if (fontattr!=fa) fontchanged=1; fontattr=fa; } void Xframe::SetFontSize(int fs) { if (fontsize!=fs) fontchanged=1; fontsize=fs; } void Xframe::SetFontFaceAttributesSize(int ff, char *fn, int fa, int fs) { SetFontFace(ff, fn); SetFontAttributes(fa); SetFontSize(fs); } void Xframe::SetFontFaceAttributesSize(char *fn, int fa, int fs) { SetFontFace(FONT_NAMED, fn); SetFontAttributes(fa); SetFontSize(fs); } void Xframe::SetFontFaceAttributesSize(string fn, int fa, int fs) { SetFontFace(FONT_NAMED, fn.getcstr()); SetFontAttributes(fa); SetFontSize(fs); } void Xframe::SetFontFaceAttributesSize(int ff, int fa, int fs) { if (ff==FONT_NAMED) ff=FW_DONTCARE; SetFontFace(ff, ""); SetFontAttributes(fa); SetFontSize(fs); } void Xframe::SetFont(void) { LOGFONT lf; if (!fontchanged) return; fontchanged=0; MakeLogfont(lf); lf.lfHeight=-fontsize; if (fontattr&FONT_BOLD) lf.lfWeight=700; else lf.lfWeight=400; if (fontattr&FONT_ITALIC) lf.lfItalic=1; if (fontattr&FONT_UNDERLINE) lf.lfUnderline=1; if (fontattr&FONT_STRIKEOUT) lf.lfStrikeOut=1; if (fontattr&FONT_FIXED) lf.lfPitchAndFamily=FIXED_PITCH; if (fontface&FONT_ROMAN) lf.lfPitchAndFamily|=FF_ROMAN; else if (fontface&FONT_SANS_SERIF) lf.lfPitchAndFamily|=FF_SWISS; else if (fontface&FONT_NAMED) { lf.lfPitchAndFamily&=~FIXED_PITCH; strcpy(lf.lfFaceName, fontname); } HFONT f=CreateFontIndirect(&lf); if (f==NULL) f=crappydefaultfont; if (f==currentfont) return; if (tout!=NULL) bitmapdc=hdc; SelectObject(bitmapdc, f); if (mode==AUTOMATIC_MODE) { start(); SelectObject(hdc, f); stop(); } if (currentfont!=crappydefaultfont && currentfont!=ansifixedfont) DeleteObject(currentfont); currentfont=f; GetTextMetrics(bitmapdc, ¤tmetric); gotmetrics=1; } void Xframe::SetFont(HFONT f) { fontchanged=0; if (f==NULL) f=crappydefaultfont; if (f==currentfont) return; if (tout!=NULL) bitmapdc=hdc; SelectObject(bitmapdc, f); if (mode==AUTOMATIC_MODE) { start(); SelectObject(hdc, f); stop(); } if (currentfont!=crappydefaultfont && currentfont!=ansifixedfont) DeleteObject(currentfont); currentfont=f; GetTextMetrics(bitmapdc, ¤tmetric); gotmetrics=1; } void Xframe::UseDefaultFont(void) { SetFontFaceAttributesSize("FixedSys", FONT_FIXED, 12); return; // the rest has no effect, but should work fontchanged=0; if (currentfont==crappydefaultfont) return; if (tout!=NULL) bitmapdc=hdc; SelectObject(bitmapdc, crappydefaultfont); if (mode==AUTOMATIC_MODE) { start(); SelectObject(hdc, crappydefaultfont); stop(); } if (currentfont!=crappydefaultfont && currentfont!=ansifixedfont) DeleteObject(currentfont); currentfont=crappydefaultfont; GetTextMetrics(bitmapdc, ¤tmetric); gotmetrics=1; } void UseDefaultFont(void) { if (mainframe==NULL) DefaultMake(); mainframe->UseDefaultFont(); } TEXTMETRIC & Xframe::GetFontMetrics(void) { if (fontchanged) SetFont(); if (tout!=NULL) bitmapdc=hdc; if (!gotmetrics) GetTextMetrics(bitmapdc, ¤tmetric); gotmetrics=1; return currentmetric; } HFONT Xframe::GetFont(void) { if (fontchanged) SetFont(); return currentfont; } void SetFontFace(int ff, char *fn) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFace(ff, fn); } void SetFontFace(char *fn) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFace(fn); } void SetFontFace(string fn) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFace(fn.getcstr()); } void SetFontAttributes(int fa) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontAttributes(fa); } void SetFontSize(int fs) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontSize(fs); } void SetFontFaceAttributesSize(int ff, char *fn, int fa, int fs) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFaceAttributesSize(ff, fn, fa, fs); } void SetFontFaceAttributesSize(char *fn, int fa, int fs) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFaceAttributesSize(FONT_NAMED, fn, fa, fs); } void SetFontFaceAttributesSize(string fn, int fa, int fs) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFaceAttributesSize(FONT_NAMED, fn.getcstr(), fa, fs); } void SetFontFaceAttributesSize(int ff, int fa, int fs) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFaceAttributesSize(ff, fa, fs); } void Xframe::WriteText(char *s) { if (fontchanged) SetFont(); if (textpenrgb!=penrgb) { SetTextColor(bitmapdc, penrgb); if (mode==AUTOMATIC_MODE) { start(); SetTextColor(hdc, penrgb); stop(); } textpenrgb=penrgb; } int len=strlen(s); TextOut(bitmapdc, (int)penx, (int)peny, s, len); if (mode==AUTOMATIC_MODE) { start(); TextOut(hdc, (int)penx, (int)peny, s, len); stop(); } } void WriteText(char *s) { if (mainframe==NULL) DefaultMake(); mainframe->WriteText(s); } void Xframe::WriteTextf(char *patt, ...) { char tmp[1000]; va_list a; va_start(a, patt); _vsnprintf(tmp, 999, patt, a); WriteText(tmp); } void WriteTextf(char *patt, ...) { char tmp[1000]; if (mainframe==NULL) DefaultMake(); va_list a; va_start(a, patt); _vsnprintf(tmp, 999, patt, a); mainframe->WriteText(tmp); } void Xframe::WriteText(string s) { WriteText(s.c_str()); } void WriteText(string s) { WriteText(s.c_str()); } void Xframe::MeasureText(char *s, int &w, int &h) { if (fontchanged) SetFont(); SIZE sz; int len=strlen(s); GetTextExtentPoint32(bitmapdc, s, len, &sz); w=sz.cx; h=sz.cy; } void Xframe::MeasureText(string s, int &w, int &h) { MeasureText(s.getcstr(), w, h); } void Xframe::MeasureText(char c, int &w, int &h) { char temp[2]; temp[0]=c; temp[1]=0; MeasureText(temp, w, h); } void MeasureText(char *s, int &w, int &h) { if (mainframe==NULL) DefaultMake(); mainframe->MeasureText(s, w, h); } void MeasureText(string s, int &w, int &h) { if (mainframe==NULL) DefaultMake(); mainframe->MeasureText(s.getcstr(), w, h); } void MeasureText(char c, int &w, int &h) { if (mainframe==NULL) DefaultMake(); mainframe->MeasureText(c, w, h); } void Xframe::Clear(void) { FillRect(bitmapdc, make_rect_xywh(0,0,width,height), whitebrush); if (mode==AUTOMATIC_MODE) { start(); FillRect(hdc, make_rect_xywh(0,0,width,height), whitebrush); stop(); } } void Clear(void) { if (mainframe==NULL) DefaultMake(); mainframe->Clear(); } const double deg360=1.0, deg60=1.0/6.0, deg180=0.5, deg240=2.0/3.0; double antihls(double n1, double n2, double h) { int times=(int)(h/deg360); h-=times*deg360; if (h<0.0) h=h+deg360; if (hbst) bst=G; if (B>bst) bst=B; double dst=R; if (G=G && R>=B) h=(G-B)/delta; else if (G>=R && G>=B) h=2.0+(B-R)/delta; else h=4.0+(R-G)/delta; if (h<0.0) h+=6.0; H=h*deg60; } int EncodeColor0255(int r, int g, int b) { if (r<0) r=0; if (r>255) r=255; if (g<0) g=0; if (g>255) g=255; if (b<0) b=0; if (b>255) b=255; return (b<<16)|(g<<8)|(r); } void DecodeColor0255(int c, int &r, int &g, int &b) { r=c&255; g=(c>>8)&255; b=(c>>16)&255; } void DecodeColor(int c, double &r, double &g, double &b) { r=(c&255)/255.0; g=((c>>8)&255)/255.0; b=((c>>16)&255)/255.0; } int EncodeColor(double rr, double gg, double bb) { int r=(int)(255*rr+0.5), g=(int)(255*gg+0.5), b=(int)(255*bb+0.5); if (r<0) r=0; if (r>255) r=255; if (g<0) g=0; if (g>255) g=255; if (b<0) b=0; if (b>255) b=255; return (b<<16)|(g<<8)|(r); } void Xframe::PenWidthColor(int w, int c) { if (w<0) w=0; if (c==penrgb && w==penw) return; if (currentpen!=blackpen) { SelectObject(bitmapdc, blackpen); if (mode==AUTOMATIC_MODE) { start(); SelectObject(hdc, blackpen); stop(); } DeleteObject(currentpen); currentpen=(HPEN)blackpen; } penw=w; penrgb=c; if (c==0 && w==1) return; currentpen=CreatePen(PS_SOLID, w, c); SelectObject(bitmapdc, currentpen); if (mode==AUTOMATIC_MODE) { start(); SelectObject(hdc, currentpen); stop(); } } void PenWidthColor(int w, int c) { if (mainframe==NULL) DefaultMake(); mainframe->PenWidthColor(w, c); } void Xframe::PenWidthColor0255(int w, int r, int g, int b) { if (r<0) r=0; if (r>255) r=255; if (g<0) g=0; if (g>255) g=255; if (b<0) b=0; if (b>255) b=255; PenWidthColor(w, (b<<16)|(g<<8)|(r)); } void PenWidthColor0255(int w, int r, int g, int b) { if (mainframe==NULL) DefaultMake(); mainframe->PenWidthColor0255(w, r, g, b); } void Xframe::PenWidthColor(int w, double rr, double gg, double bb) { PenWidthColor0255(w, (int)(255*rr+0.5), (int)(255*gg+0.5), (int)(255*bb+0.5)); } void PenWidthColor(int w, double rr, double gg, double bb) { if (mainframe==NULL) DefaultMake(); mainframe->PenWidthColor(w, rr, gg, bb); } void Xframe::PenColor(int c) { PenWidthColor(penw, c); } void PenColor(int c) { if (mainframe==NULL) DefaultMake(); mainframe->PenColor(c); } void Xframe::PenColor0255(int r, int g, int b) { PenWidthColor0255(penw, r, g, b); } void PenColor0255(int r, int g, int b) { if (mainframe==NULL) DefaultMake(); mainframe->PenColor0255(r, g, b); } void Xframe::PenColor(double rr, double gg, double bb) { PenWidthColor(penw, rr, gg, bb); } void PenColor(double rr, double gg, double bb) { if (mainframe==NULL) DefaultMake(); mainframe->PenColor(rr, gg, bb); } void Xframe::PenWidth(int w) { PenWidthColor(w, penrgb); } void PenWidth(int w) { if (mainframe==NULL) DefaultMake(); mainframe->PenWidth(w); } void Xframe::Show(void) { if (mode==OFFSCREEN_MODE) repaint(); } void Show(void) { if (mainframe==NULL) DefaultMake(); mainframe->Show(); } void Pause(double secs) { Sleep((DWORD)(secs*1000.0+0.5)); } void PrintStats(const TEXTMETRIC &tm) { printf("height=%d, Ascent=%d, Descent=%d, ILead=%d, ELead=%d\n", tm.tmHeight, tm.tmAscent, tm.tmDescent, tm.tmInternalLeading, tm.tmExternalLeading); printf("AvWidth=%d, MaxWidth=%d, FirstChar=%d, LastChar=%d\n", tm.tmAveCharWidth, tm.tmMaxCharWidth, tm.tmFirstChar, tm.tmLastChar); printf("cx,cyscreen=%d,%d cx,cyfullscreen=%d,%d\n", SMcxscreen, SMcyscreen, SMcxfullscreen, SMcyfullscreen); printf("cx,cyicon=%d,%d cx,cysmicon=%d,%d\n", SMcxicon, SMcyicon, SMcxsmicon, SMcysmicon); printf("cycaption=%d, cx,cyborder=%d,%d, cx,cysizeframe=%d,%d\n", SMcycaption, SMcxborder, SMcyborder, SMcxsizeframe, SMcysizeframe); printf("using width+2*cxsizeframe=%d and height+cycaption+2*cysizeframe=%d\n", 2*SMcxsizeframe, SMcycaption+2*SMcysizeframe); } int __stdcall programthreadfn(void *ignore) { ignore=ignore; SMcxscreen=GetSystemMetrics(SM_CXSCREEN); SMcyscreen=GetSystemMetrics(SM_CYSCREEN); SMcxfullscreen=GetSystemMetrics(SM_CXFULLSCREEN); SMcyfullscreen=GetSystemMetrics(SM_CYFULLSCREEN); SMcycaption=GetSystemMetrics(SM_CYCAPTION); SMcxborder=GetSystemMetrics(SM_CXBORDER); SMcyborder=GetSystemMetrics(SM_CYBORDER); SMcxicon=GetSystemMetrics(SM_CXICON); SMcyicon=GetSystemMetrics(SM_CYICON); SMcxsmicon=GetSystemMetrics(SM_CXSMICON); SMcysmicon=GetSystemMetrics(SM_CYSMICON); SMcxsizeframe=GetSystemMetrics(SM_CXSIZEFRAME); SMcysizeframe=GetSystemMetrics(SM_CYSIZEFRAME); SMcymenu=GetSystemMetrics(SM_CYMENU); textframe=new Xframe(800, 800, "starting", 0, 0, 1, text); SetConsoleCaption("Console: RUNNING"); int er=setjmp(exitplace); if (er==0) main(); while (threadcount>0) Sleep(100); SetConsoleCaption("Console: PROGRAM TERMINATED"); ilog("Program main() exitted.\n"); return 1; } void Exit(void) { longjmp(exitplace, 1); } int __stdcall WinMain(HINSTANCE this_inst, HINSTANCE prev_inst, char *cmdline, int cmdshow) { MSG msg; struct _timeb timebuffer; char *timeline; logfile=NULL; oldlog[0]=0; _ftime(&timebuffer); timeline=ctime(&timebuffer.time); ilog("run started %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20]); time_zero=timebuffer.time; cmdshow=cmdshow; for (int hi=0; hi=WM_USER) { WindowProc(NULL, msg.message, msg.wParam, msg.lParam); } else DispatchMessage(&msg); } WaitForSingleObjectEx(programthread,INFINITE,1); _ftime(&timebuffer); timeline=ctime(&timebuffer.time); ilog("run ended %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20]); if (logfile!=NULL) fclose(logfile); return (msg.wParam); } int CALLBACK ffef(const LOGFONT *lf, const TEXTMETRIC *tm, unsigned long FontType, long lParam) // this function used by call EnumFontFamiliesEx(hdc, NULL, ffef, 0, 0); { if (tm->tmItalic || tm->tmStruckOut || tm->tmUnderlined) log("**%s*%s*%s** ", tm->tmItalic?"italic":"", tm->tmStruckOut?"strikeout":"", tm->tmUnderlined?"undeline":""); log("'%s' ", lf->lfFaceName); int c=lf->lfCharSet; if (c==ANSI_CHARSET) log("ansi"); else if (c==BALTIC_CHARSET) log("baltic"); else if (c==CHINESEBIG5_CHARSET) log("chinese_big_5"); else if (c==DEFAULT_CHARSET) log("default"); else if (c==EASTEUROPE_CHARSET) log("east_europe"); else if (c==GB2312_CHARSET) log("gb2312"); else if (c==GREEK_CHARSET) log("greek"); else if (c==HANGUL_CHARSET) log("hangul"); else if (c==MAC_CHARSET) log("mac"); else if (c==OEM_CHARSET) log("oem"); else if (c==RUSSIAN_CHARSET) log("russian"); else if (c==SHIFTJIS_CHARSET) log("shift_jis"); else if (c==SYMBOL_CHARSET) log("symbol"); else if (c==TURKISH_CHARSET) log("turkish"); else if (c==JOHAB_CHARSET) log("johab"); else if (c==HEBREW_CHARSET) log("hebrew"); else if (c==ARABIC_CHARSET) log("arabic"); else if (c==THAI_CHARSET) log("thai"); else log("unknown-charset"); log("(%d) ", c); if (tm->tmWeight==700) log("(bold) "); else if (tm->tmWeight!=400) log("(weight=%d) ", tm->tmWeight); int p=tm->tmPitchAndFamily&3; if (p==FIXED_PITCH) log("fixed "); else if (p==VARIABLE_PITCH) log("variable "); else if (p==DEFAULT_PITCH) log("DEFAULT_PITCH "); else if (p==3) log("ANY PITCH ", p); else log("pitch=%d ", p); int f=tm->tmPitchAndFamily&0xF0; if (f==FF_DECORATIVE) log("decorative "); else if (f==FF_DONTCARE) log("FF_DONTCARE "); else if (f==FF_MODERN) log("modern "); else if (f==FF_ROMAN) log("roman "); else if (f==FF_SCRIPT) log("script "); else if (f==FF_SWISS) log("swiss "); else log("family=%d ", f); log("\n"); return 1; } const int maxnumberoffonts=100; int numberoffonts=0; char **fontnames=NULL; char lastfontname[maxnumberoffonts]; int CALLBACK ffef1(const LOGFONT *lf, const TEXTMETRIC *tm, unsigned long FontType, long lParam) { const char *thisname=lf->lfFaceName; if (strcmp(thisname, lastfontname)!=0) { strcpy(lastfontname,thisname); numberoffonts+=1; } return 1; } int CALLBACK ffef2(const LOGFONT *lf, const TEXTMETRIC *tm, unsigned long FontType, long lParam) { const char *thisname=lf->lfFaceName; if (strcmp(thisname, lastfontname)!=0) { strcpy(lastfontname,thisname); if (numberoffontsmaxnumberoffonts) numberoffonts=maxnumberoffonts; fontnames=new char *[numberoffonts]; numberoffonts=0; strcpy(lastfontname,"HippopotamusWithCherries"); EnumFontFamiliesEx(hdc, NULL, ffef2, 0, 0); if (numberoffonts>maxnumberoffonts) numberoffonts=maxnumberoffonts; } int Xframe::GetNumberOfFonts(void) { if (numberoffonts==0) reallyfindfonts(bitmapdc); return numberoffonts; } int GetNumberOfFonts(void) { if (mainframe==NULL) DefaultMake(); return mainframe->GetNumberOfFonts(); } string Xframe::GetFontName(int i) { if (numberoffonts==0) reallyfindfonts(bitmapdc); if (i<0 || i>=numberoffonts) return string(""); return string(fontnames[i]); } string GetFontName(int i) { if (mainframe==NULL) DefaultMake(); return mainframe->GetFontName(i); } void Xframe::DrawImage(Image *im, double inx, double iny) { if (im==NULL) return; int w, h, px=(int)inx, py=(int)iny; im->GetSize(w,h); int **pix=im->GetPixels(); for (int y=0; yDrawImage(i, x, y); } void Xframe::DrawImage(Image *im) { DrawImage(im, penx, peny); } void DrawImage(Image *i) { if (mainframe==NULL) DefaultMake(); mainframe->DrawImage(i); } void Xframe::Scroll(int dx, int dy, Region &r) { RECT cliprect; cliprect.top=0; cliprect.left=0; cliprect.right=width; cliprect.bottom=height; ScrollWindowEx(hwnd, dx, dy, NULL, &cliprect, NULL, &r, 0); } void Scroll(int dx, int dy, Region &r) { if (mainframe==NULL) DefaultMake(); mainframe->Scroll(dx,dy,r); } Xframe *GetMainWindow() { if (mainframe==NULL) DefaultMake(); return mainframe; } Xframe *GetConsoleWindow() { return textframe; } void painttextplease(Xframe *fr) { int ht, wd; int winw, winh, wantbuff=keyboardmode==NORMAL_MODE; char **data; fr->GetSize(winw, winh); TextOutput *tout=fr->gettext(); tout->get(ht, wd, data); HDC hdc=fr->getpaintDC(); POINT pt; HGDIOBJ blackpen=GetStockObject(BLACK_PEN); SelectObject(hdc,blackpen); fr->SetFont(ansifixedfont); SelectObject(hdc, ansifixedfont); TEXTMETRIC currentmetric; GetTextMetrics(hdc, ¤tmetric); int chw=currentmetric.tmAveCharWidth, chh=currentmetric.tmHeight+currentmetric.tmExternalLeading+1; if (chw==0) chw=8; int maxx=wd*chw+6, maxy=(chh+1)*ht+1; int maxmaxy=maxy+(wantbuff ? chh+1+5 : 1); FillRect(hdc, make_rect_xywh(0,0,maxx,maxmaxy), whitebrush); MoveToEx(hdc, 0, 0, &pt); LineTo(hdc, maxx, 0); LineTo(hdc, maxx, maxy); LineTo(hdc, 0, maxy); LineTo(hdc, 0, 0); if (wantbuff) { MoveToEx(hdc, 0, maxy+3, &pt); LineTo(hdc, maxx, maxy+3); LineTo(hdc, maxx, maxmaxy); LineTo(hdc, 0, maxmaxy); LineTo(hdc, 0, maxy+3); } if (!tout->sized) { Region r; fr->GetLocation(r); int neww=maxx+2*SMcxborder+2*SMcxsizeframe; int newh=maxmaxy+SMcycaption+2*SMcyborder+2*SMcysizeframe+SMcymenu; MoveWindow(fr->getHWND(), r.left, r.top, neww, newh, 1); fr->internallysetsize(neww, newh); tout->sized=1; } int numc=winw/chw+1; if (numc>wd) numc=wd; char ready[300]; for (int i=0; isavein(savf); fclose(savf); char msg[1000]; sprintf(msg, "Console text saved in\n %s", fn.getcstr()); MessageBox(NULL, msg, "Text Output Saved", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); } } return 0; } case XMmenu_capture_graphics: { int ok=0; string fn=""; if (mainframe==NULL) MessageBox(NULL, "No graphics window to save", "Error", MB_OK | MB_ICONERROR | MB_TASKMODAL); else { fn=SaveAsFileDialog("capture.bmp", "", "bmp", "Save Graphics As .BMP File"); if (fn!="") ok=1; } if (ok) { FILE *savf=fopen(fn.getcstr(), "w"); if (savf==NULL) { char err[1000]; sprintf(err, "Could not create file:\n %s", fn.getcstr()); MessageBox(NULL, err, "File Error", MB_OK | MB_ICONERROR | MB_TASKMODAL); } else { mainframe->SaveAsBMP(savf); fclose(savf); char msg[1000]; sprintf(msg, "Graphics saved in\n %s", fn.getcstr()); MessageBox(NULL, msg, "Graphics Saved", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); } } return 0; } default: { int item=LOWORD(wparam); if (1) { if (fr!=textframe && (events_wanted & MENU_SELECTED)) register_event(MENU_SELECTED, item, 0, fr); } else { printf("uncaught WM_COMMAND %d\n", item); log("uncaught WM_COMMAND %d\n", item); } } } break; } case WM_CLOSE: { if (fr==NULL) break; else if (fr!=textframe && (events_wanted & WINDOW_CLOSED)) { register_event(WINDOW_CLOSED, 0, 0, fr); return 0; } else { fr->Close(); return 0; } break; } case WM_DESTROY: { if (fr!=NULL) { fr->dispose(); return 0; } break; } case XMcreate: { Xframe *fr=(Xframe *)lparam; fr->threadedcreate(); SetForegroundWindow(window); SetFocus(window); return 0; } case XMdestroy: { Xframe *fr=(Xframe *)lparam; HWND w=fr->getHWND(); int k=DestroyWindow(w); if (k==0) PrintLastError("WindowProc:XMdestroy:DestroyWindow"); return 0; } case WM_SYSKEYDOWN: { // printf("WM_SYSKEYDOWN %d %X\n", wparam, lparam); break; } case WM_SYSKEYUP: { // printf("WM_SYSKEYUP message %d %X\n",wparam,lparam); break; } case WM_SYSCHAR: { // printf("WM_SYSCHAR %d %X\n", wparam, lparam); break; } case WM_KEYDOWN: { // printf("WM_KEYDOWN %d %X\n", wparam, lparam); break; } case WM_KEYUP: { // if ((lparam&0x00ffffff)==last3char) break; if (wparam==8 || wparam==9 || wparam==13 || wparam==16 || wparam==17 || wparam==20 || wparam==27 || wparam==32 || wparam>=48 && wparam<=57 || wparam>=65 && wparam<=92 || wparam>=96 && wparam<=111 || wparam>=128) break; wparam+=128; if (wparam==174) wparam=127; /* NO BREAK DELIBERATELY */ } case WM_CHAR: { // printf("WM_CHAR %d %X\n", wparam, lparam); if (fr!=textframe && (events_wanted & KEY_TYPED) && wparam!=3) { register_event(KEY_TYPED, wparam, 0, fr); return 0; } if (fr!=textframe && (events_wanted & CONTROL_C_TYPED) && wparam==3) { register_event(KEY_TYPED, wparam, 0, fr); return 0; } if (keyboardmode==DIRECT_MODE && wparam!=3) { if (keyboardinputlength=32 && wparam<=126 || wparam==10) && (keyboardinputlength0) { keyboardinputlength-=1; if (keyboardinput[keyboardinputlength]=='\n') newlinesinbuffer-=1; keyboardinput[keyboardinputlength]=0; print_flush(); } else if (wparam==24) { keyboardinputlength=0; newlinesinbuffer=0; keyboardinput[keyboardinputlength]=0; print_flush(); } else if (wparam==3) { ilog("Control-C\n"); TerminateThread(programthread,1); killed=1; PostQuitMessage(1); } return 0; } case WM_LBUTTONDOWN: { mousedownx=LOWORD(lparam); mousedowny=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_PRESS_L)) register_event(MOUSE_PRESS_L, mousedownx, mousedowny, fr); mouseupx=-999888; mouseupy=-999888; mousebutton=1; return 0; } case WM_RBUTTONDOWN: { mousedownx=LOWORD(lparam); mousedowny=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_PRESS_R)) register_event(MOUSE_PRESS_R, mousedownx, mousedowny, fr); mouseupx=-999888; mouseupy=-999888; mousebutton=2; return 0; } case WM_MBUTTONDOWN: { mousedownx=LOWORD(lparam); mousedowny=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_PRESS_M)) register_event(MOUSE_PRESS_M, mousedownx, mousedowny, fr); mouseupx=-999888; mouseupy=-999888; mousebutton=3; return 0; } case WM_LBUTTONUP: { mouseupx=LOWORD(lparam); mouseupy=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_RELEASE_L)) register_event(MOUSE_RELEASE_L, mouseupx, mouseupy, fr); if (fr!=textframe && (events_wanted & MOUSE_CLICK_L) && (mouseupx-mousedownx)*(mouseupx-mousedownx)<5 && (mouseupy-mousedowny)*(mouseupy-mousedowny)<5 ) register_event(MOUSE_CLICK_L, mouseupx, mouseupy, fr); mousebutton=1; return 0; } case WM_RBUTTONUP: { mouseupx=LOWORD(lparam); mouseupy=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_RELEASE_R)) register_event(MOUSE_RELEASE_R, mouseupx, mouseupy, fr); if (fr!=textframe && (events_wanted & MOUSE_CLICK_R) && (mouseupx-mousedownx)*(mouseupx-mousedownx)<5 && (mouseupy-mousedowny)*(mouseupy-mousedowny)<5 ) register_event(MOUSE_CLICK_R, mouseupx, mouseupy, fr); mousebutton=2; return 0; } case WM_MBUTTONUP: { mouseupx=LOWORD(lparam); mouseupy=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_RELEASE_M)) register_event(MOUSE_RELEASE_M, mouseupx, mouseupy, fr); if (fr!=textframe && (events_wanted & MOUSE_CLICK_M) && (mouseupx-mousedownx)*(mouseupx-mousedownx)<5 && (mouseupy-mousedowny)*(mouseupy-mousedowny)<5 ) register_event(MOUSE_CLICK_M, mouseupx, mouseupy, fr); mousebutton=3; return 0; } case WM_LBUTTONDBLCLK: { mouseupx=LOWORD(lparam); mouseupy=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_DCLICK_L) ) register_event(MOUSE_DCLICK_L, mouseupx, mouseupy, fr); mousebutton=1; return 0; } case WM_MBUTTONDBLCLK: { mouseupx=LOWORD(lparam); mouseupy=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_DCLICK_M) ) register_event(MOUSE_DCLICK_M, mouseupx, mouseupy, fr); mousebutton=1; return 0; } case WM_RBUTTONDBLCLK: { mouseupx=LOWORD(lparam); mouseupy=HIWORD(lparam); if (fr!=textframe && (events_wanted & MOUSE_DCLICK_R) ) register_event(MOUSE_DCLICK_R, mouseupx, mouseupy, fr); mousebutton=1; return 0; } case WM_NCMOUSEMOVE: { // int x=LOWORD(lparam); // int y=HIWORD(lparam); // printf("NCMOUSEMOVE (%d, %d)\n", x, y); return 0; } case WM_ERASEBKGND: { if (fr->istext()) break; return 1; } case WM_PAINT: { // thecount+=1; // int idx=fr->GetIndexNumber(); // if (idx!=1) printf("%d: PAINT #%d\n", thecount, idx); if (fr!=NULL) { PAINTSTRUCT ps; if (fr->getmode()==AUTOMATIC_MODE) fr->startredraw(); HDC hdc=BeginPaint(window,&ps); RECT r; GetWindowRect(window, &r); int dw=2*SMcxsizeframe, dh=SMcycaption+2*SMcysizeframe, ow, oh; fr->GetSize(ow, oh); if (fr->HasMenuBar()) dh+=SMcymenu; int w=r.right-r.left-dw, h=r.bottom-r.top-dh; // if (idx!=1) printf(" temporarily restoring from %dx%d to %dx%d\n", ow, oh, w, h); fr->internallysetsize(w, h); fr->setpaintDC(hdc); fr->autopaint(); fr->setpaintDC(NULL); ReleaseDC(window,hdc); EndPaint(window,&ps); // if (idx!=1) printf(" returning to %dx%d\n", ow, oh); fr->internallysetsize(ow, oh); if (fr->getmode()==AUTOMATIC_MODE) fr->finishredraw(); if (fr->isminimal && fr!=textframe && (events_wanted & WINDOW_RESTORED)) register_event(WINDOW_RESTORED, 0, 0, fr); fr->isminimal=0; if (fr!=textframe && (events_wanted & WINDOW_REPAINTED)) register_event(WINDOW_REPAINTED, 0, 0, fr); return 0; } break; } case WM_TIMER: { if (wparam&1) KillTimer(window, wparam); if (events_wanted & TIMER_SIGNAL) register_event(TIMER_SIGNAL, wparam, 0, NULL, 1); break; } case WM_MOUSEMOVE: { // int x=LOWORD(lparam), y=HIWORD(lparam); // int pressed=(wparam&(MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))?1:0; // printf("MOUSE MOVE %d %d %d\n", x, y, pressed); break; } case WM_MOVE: { int x=LOWORD(lparam), y=HIWORD(lparam); fr->internallysetpos(x,y); break; } case WM_SIZE: { int w=LOWORD(lparam), h=HIWORD(lparam); if (wparam==SIZE_MINIMIZED) { fr->isminimal=1; fr->internallysetsize(0,0); if (fr!=textframe && (events_wanted & WINDOW_MINIMIZED)) register_event(WINDOW_MINIMIZED, 0, 0, fr); break; } if (wparam==SIZE_MAXIMIZED) { if (fr->isminimal && fr!=textframe && (events_wanted & WINDOW_RESTORED)) register_event(WINDOW_RESTORED, 0, 0, fr); fr->isminimal=0; fr->ismaximal=1; if (fr!=textframe && (events_wanted & WINDOW_RESIZED)) register_event(WINDOW_RESIZED, w, h, fr); fr->internallysetsize(w,h); break; } if (wparam==SIZE_RESTORED) { int msg=fr->ismaximal?WINDOW_RESIZED:WINDOW_RESTORED; if ((fr->isminimal || fr->ismaximal) && fr!=textframe && (events_wanted & msg)) { int ow, oh; fr->GetSize(ow,oh); if (ow!=w || oh!=h) { register_event(msg, w, h, fr); fr->internallysetsize(w,h); } if (msg==WINDOW_RESTORED) InvalidateRect(window,NULL,0); } fr->isminimal=0; fr->ismaximal=0; } fr->ongoingw=w; fr->ongoingh=h; break; } case WM_EXITSIZEMOVE: { int w, h; fr->GetSize(w,h); fr->isminimal=0; fr->ismaximal=0; if (w!=fr->ongoingw || h!=fr->ongoingh) { fr->resizetoongoing(); if (fr!=textframe && (events_wanted & WINDOW_RESIZED)) register_event(WINDOW_RESIZED, fr->ongoingw, fr->ongoingh, fr); } break; } default: { if (msg>=XMaddedmin && msg<=XMaddedmax) handlers[msg-XMaddedmin](fr, msg, wparam, lparam); else break; return 0; } } return (DefWindowProc(window,msg,wparam,lparam)); } void Xframe::ReobtainDC(void) { if (mode!=AUTOMATIC_MODE) return; hdc=GetDC(hwnd); MoveToEx(hdc, (int)penx, (int)peny, NULL); SelectObject(hdc,currentfont); SetBkMode(hdc, TRANSPARENT); SelectObject(hdc,currentpen); SetTextColor(hdc,textpenrgb); } void Xframe::ReleaseDC(void) { if (mode==AUTOMATIC_MODE && hdc!=NULL) { ::ReleaseDC(hwnd, hdc); hdc=NULL; } } void Xframe::start(void) { if (batching) return; DWORD r=WaitForSingleObjectEx(drawingmutex,1000,0); } void Xframe::startredraw(void) { if (repainthappening) return; DWORD r=WaitForSingleObjectEx(drawingmutex,1000,0); repainthappening=1; } void Xframe::stop(void) { if (batching) return; ReleaseMutex(drawingmutex); } void Xframe::finishredraw(void) { repainthappening=0; ReleaseMutex(drawingmutex); } void Xframe::StartBatching(void) { if (batching) return; DWORD r=WaitForSingleObjectEx(drawingmutex,1000,0); batching=1; } void Xframe::StopBatching(void) { if (!batching) return; ReleaseMutex(drawingmutex); batching=0; } int Xframe::IsBatching(void) { return batching; } void StartBatching(void) { if (mainframe==NULL) DefaultMake(); mainframe->StartBatching(); } void StopBatching(void) { if (mainframe==NULL) DefaultMake(); mainframe->StopBatching(); } int IsBatching(void) { if (mainframe==NULL) DefaultMake(); return mainframe->IsBatching(); } void SetKeyboardMode(int m) { keyboardmode=m; if (text!=NULL) text->sized=0; print_flush(); } char read_char_if_ready(void) { if (keyboardinputlength==0) return 0; char ans=keyboardinput[0]; if (ans==10) newlinesinbuffer-=1; for (int i=0; i mouse only, ignore the keyboard // kb==1 -> wait for mouse or just a keypress // kb==2 -> wait for mouse or whole line from keyboard // kb==3 -> mouse basic event or just a keypress // wt==0 -> don't wait, just test. { if (wt) { if (kb==1 || kb==3) SetConsoleCaption("Console: WAITING FOR MOUSE OR KEYPRESS"); else if (kb==2) SetConsoleCaption("Console: WAITING FOR MOUSE OR INPUT LINE"); else SetConsoleCaption("Console: WAITING FOR MOUSE"); } while (1) { if (killed) break; if (mouseupx!=-999888) break; if (kb==1 && keyboardinputlength!=0) break; if (kb==3 && keyboardinputlength!=0) break; if (kb==3 && mousedownx!=-999888) break; if (kb==2 && newlinesinbuffer!=0) break; if (!wt) { b=0; return 0; } Sleep(100); } if (wt) SetConsoleCaption("Console: RUNNING"); x0=mousedownx; y0=mousedowny; x1=mouseupx; y1=mouseupy; if (mouseupx!=-999888) b=mousebutton; else if (kb==3 && mousedownx!=-999888) b=-mousebutton; else b=0; mousedownx=-999888; mouseupx=-999888; return 1; } void WaitForMouse(int &x0, int &y0, int &x1, int &y1, int &b) { StartMonitoringMouse(); MouseInternal(1, 0, x0, y0, x1, y1, b); } void WaitForMouseOrKeyPress(int &x0, int &y0, int &x1, int &y1, int &b) { StartMonitoringMouse(); MouseInternal(1, 1, x0, y0, x1, y1, b); } void WaitForMouseEventOrKeyPress(int &x0, int &y0, int &b) { StartMonitoringMouse(); int x1=-9, y1=-9; MouseInternal(1, 3, x0, y0, x1, y1, b); if (b>0) { x0=x1; y0=y1; } } void WaitForMouseOrInput(int &x0, int &y0, int &x1, int &y1, int &b) { StartMonitoringMouse(); MouseInternal(1, 2, x0, y0, x1, y1, b); } int CheckKeyPressed(void) { return keyboardinputlength!=0; } int CheckInputReady(void) { return newlinesinbuffer!=0; } int CheckMouseAction(void) { return mouseupx!=-999888; } void GetMouseAction(int &x0, int &y0, int &x1, int &y1, int &b) { MouseInternal(0, 0, x0, y0, x1, y1, b); } void GetMouseEvent(int &x0, int &y0, int &b) { int x1=-9, y1=-9; MouseInternal(0, 3, x0, y0, x1, y1, b); if (b>0) { x0=x1; y0=y1; } } char read_char_no_wait(void) { return read_char_if_ready(); } char read_char_no_wait_no_echo(void) { return read_char_if_ready_no_echo(); } char read_char(void) { SetConsoleCaption("Console: WAITING FOR INPUT"); while (newlinesinbuffer==0 && !killed) Sleep(100); SetConsoleCaption("Console: RUNNING"); return read_char_if_ready(); } char read_char_no_echo(void) { SetConsoleCaption("Console: WAITING FOR INPUT"); while (newlinesinbuffer==0 && !killed) Sleep(100); SetConsoleCaption("Console: RUNNING"); return read_char_if_ready_no_echo(); } void read_cstring(char *s) { int i=0, gotsome=0; while (!killed) { char c=read_char(); if (c<=' ') { if (gotsome) return; continue; } else gotsome=1; s[i]=c; s[i+1]=0; i+=1; } } void read_cline(char *s) { int i=0; while (!killed) { char c=read_char(); if (c=='\n') break; s[i]=c; s[i+1]=0; i+=1; } } int read_int(void) { char s[100]; read_cstring(s); int r; sscanf(s, "%d", &r); return r; } float read_float(void) { char s[100]; read_cstring(s); float r; sscanf(s, "%f", &r); return r; } double read_double(void) { char s[100]; read_cstring(s); double r; sscanf(s, "%lf", &r); return r; } void print(int n) { print_int(n); } void print(float f) { printf("%.7e", f); } void print(double f) { printf("%.14le", f); } void print(const char *s) { print_string(s); } void print(const string &s) { print_string(s.c_str()); } void newline(void) { print_char('\n'); } void flush(void) { print_flush(); } void read(char &c) { c=read_char(); } void read_char(char &c) { c=read_char(); } void read_char_no_echo(char &c) { c=read_char_no_echo(); } void read_char_if_ready(char &c) { c=read_char_if_ready(); } void read(int &n) { n=read_int(); } void read(float &f) { f=read_float(); } void read(double &f) { f=read_double(); } void read(string &s) { char t[1000]; read_cstring(t); s=t; } void read(void) { read_char(); } string read_string(void) { string s; read(s); return s; } string read_line(void) { string s; char t[1000]; read_cline(t); s=t; return s; } string::string(int mx) { max=mx+1; data=new char[max]; data[0]=0; len=0; } string::string(void) { max=257; data=new char[max]; data[0]=0; len=0; } string::string(const char *s) { len=strlen(s); max=len+100; data=new char[max]; strcpy(data, s); } string::string(const string &s) { max=s.max; len=s.len; data=new char[max]; strcpy(data, s.data); } string string::from_int(int n) { char buff[20]; int ptr=19, neg=0; if (n<0) { neg=1; n=-n; } buff[ptr]=0; do { ptr-=1; buff[ptr]='0'+n%10; n/=10; } while (n>0); return string(buff+ptr); } string::~string(void) { delete[] data; } char *string::getcstr(void) const { return data; } char *string::c_str(void) const { return data; } string &string::operator=(const string &s) { max=s.max; len=s.len; if (data!=s.data) { data=new char[max]; strcpy(data, s.data); } return *this; } string &string::operator=(const char *s) { len=strlen(s); max=len+100; data=new char[max]; strcpy(data, s); return *this; } bool string::operator==(const string &s) const { return strcmp(data, s.data)==0; } bool string::operator!=(const string &s) const { return strcmp(data, s.data)!=0; } bool string::operator<(const string &s) const { return strcmp(data, s.data)<0; } bool string::operator>(const string &s) const { return strcmp(data, s.data)>0; } bool string::operator<=(const string &s) const { return strcmp(data, s.data)<=0; } bool string::operator>=(const string &s) const { return strcmp(data, s.data)>=0; } int string::length(void) const { return len; } int string::maximum(void) const { return max; } void string::growto(int newmax) { char *temp=new char[newmax]; strcpy(temp, data); delete[] data; data=temp; max=newmax; } string &string::append(const char *s, int slen) { int newlen=len+slen; if (newlen>=max-1) growto(max+100); strcat(data, s); len=newlen; data[len]=0; return *this; } void string::deletechars(int first, int last) { if (first<0) first=0; if (last=max-1) growto(max+100); if (pos>len) pos=len; if (pos<0) pos=0; for (int i=len; i>pos; i-=1) data[i]=data[i-1]; data[pos]=c; len=newlen; data[len]=0; } string &string::append(const char *s) { return append(s, strlen(s)); } string &string::append(const string &s) { return append(s.data, s.len); } string &string::append(char c) { char data[2]; data[0]=c; data[1]=0; return append(data, 1); } string string::operator+(const char *addition) { string s(*this); s.append(addition, strlen(addition)); return s; } string string::operator+(const string &s) { return operator+(s.data); } string string::operator+(char c) { char data[2]; data[0]=c; data[1]=0; return operator+(data); } char &string::character(int n) const { if (n<0) n=0; if (n>=len) n=len-1; return data[n]; } char &string::operator[](int n) const { if (n<0) n=0; if (n>=len) n=len-1; return data[n]; } string string::substring(int begin, int end) { if (end<0) end=len+end; if (end<0) end=0; if (begin<0) begin=len+begin; if (begin<0) begin=0; if (begin>end || begin>=len) return string(""); if (end>=len) end=len-1; int newlen=end+1-begin; string s(newlen<257 ? 257 : newlen); for (int i=begin; i<=end; i+=1) s.data[i-begin]=data[i]; s.data[newlen]=0; s.len=newlen; return s; } int string::to_int(int &ok) { int n=len, pos=0, sign=1, value=0; while (pos'9') { ok=0; return 0; } while (pos='0' && data[pos]<='9') { value=value*10+data[pos]-'0'; pos+=1; } while (pos(const char *x, const string &s) { return strcmp(x, s.getcstr())>0; } bool operator<=(const char *x, const string &s) { return strcmp(x, s.getcstr())<=0; } bool operator>=(const char *x, const string &s) { return strcmp(x, s.getcstr())>=0; } output_object::output_object(void) { ofile=NULL; } void output_object::print_char(char c) { if (ofile!=NULL) putc(c, ofile); } void output_object::print(int n) { if (ofile!=NULL) fprintf(ofile, "%d", n); } void output_object::print(double f) { if (ofile!=NULL) fprintf(ofile, "%.14le", f); } void output_object::print(float f) { if (ofile!=NULL) fprintf(ofile, "%.7e", f); } void output_object::print(const char *s) { if (ofile!=NULL) fputs(s, ofile); } void output_object::print(const string &s) { if (ofile!=NULL) fputs(s.getcstr(), ofile); } void output_object::newline(void) { if (ofile!=NULL) putc('\n', ofile); } void output_object::flush(void) { if (ofile!=NULL) fflush(ofile); } void output_object::close(void) { if (ofile!=NULL) fclose(ofile); } screen_object::screen_object(void) { ofile=stdout; } void screen_object::close(void) { } output_file::output_file(char *filename) { ofile=fopen(filename, "w"); if (ofile==NULL) { fprintf(stderr,"\nCan not open file \"%s\"\n", filename); exit(1); } } output_file::output_file(void) { ofile=NULL; } output_file::output_file(string &filename) { char *fname=filename.getcstr(); ofile=fopen(fname, "w"); if (ofile==NULL) { fprintf(stderr,"\nCan not open file \"%s\"\n", fname); exit(1); } } void input_object::rewind(void) { ::rewind(ifile); } void input_object::get(void) { if (ifile==NULL) t=NULL; else { line[0]=0; t=fgets(line, 199, ifile); } } char *input_object::read_line(void) { get(); int n=strlen(line)-1; if (line[n]=='\n') line[n]=0; return line; } input_object::input_object(void) { ifile=NULL; } void input_object::read(char &c) { get(); c=line[0]; ok=t!=NULL; } char input_object::read_char(void) { char c; read(c); return c; } void input_object::read_char(char &c) { read(c); } void input_object::read(int &i) { get(); i=strtol(line, &t, 10); ok=line!=t; } int input_object::read_int(void) { int i; read(i); return i; } void input_object::read(float &f) { get(); f=(float)strtod(line, &t); ok=line!=t; } float input_object::read_float(void) { float f; read(f); return f; } void input_object::read(double &f) { get(); f=strtod(line, &t); ok=line!=t; } double input_object::read_double(void) { double d; read(d); return d; } char *input_object::read_charstar(void) { get(); static char temp[300]; int i=0, j=0; while (1) { char c=line[i]; if (c==0 || c>' ') break; i+=1; } while (1) { char c=line[i]; if (c<=' ') { temp[j]=0; break; } temp[j]=c; i+=1; j+=1; } ok=temp[0]!=0; return temp; } string input_object::read_string(void) { char *t=read_charstar(); return string(t); } void input_object::read(string &s) { char *t=read_charstar(); s=string(t); } void input_object::read(void) { get(); } void input_object::close(void) { if (ifile!=NULL) fclose(ifile); } keyboard_object::keyboard_object(void) { ifile=stdin; } void keyboard_object::close(void) { } input_file::input_file(char *filename) { ifile=fopen(filename, "r"); if (ifile==NULL) { fprintf(stderr,"\nCan not open file \"%s\"\n", filename); exit(1); } } input_file::input_file(void) { ifile=NULL; ok=0; } input_file::input_file(string &filename) { char *fname=filename.getcstr(); ifile=fopen(fname, "w"); if (ifile==NULL) { fprintf(stderr,"\nCan not open file \"%s\"\n", fname); exit(1); } } string_scanner::string_scanner(string s) { ifile=NULL; char *t=s.getcstr(); len=strlen(t); if (t[len-1]=='\n') { len-=1; t[len]=0; } strncpy(line,t,257); ok=1; pos=0; } string_scanner::string_scanner(void) { ifile=NULL; line[0]=0; ok=0; pos=0; len=0; } void string_scanner::rewind(void) { pos=0; } void string_scanner::read(char &c) { if (pos>=len) c=0; else { c=line[pos]; pos+=1; } } char string_scanner::read_char(void) { char c; read(c); return c; } void string_scanner::read_char(char &c) { read(c); } int string_scanner::read_digit(void) { char c=0; while (pos' ') break; } if (c>='0' && c<='9') return c-'0'; return -1; } void string_scanner::read(int &i) { char *s=NULL; i=strtol(line+pos, &s, 10); ok=s!=line+pos; pos=s-line; } int string_scanner::read_int(void) { int i; read(i); return i; } void string_scanner::read(float &f) { char *s=NULL; double d=strtod(line+pos, &s); f=(float)d; ok=s!=line+pos; pos=s-line; } float string_scanner::read_float(void) { float f; read(f); return f; } void string_scanner::read(double &d) { char *s=NULL; d=strtod(line+pos, &s); ok=s!=line+pos; pos=s-line; } double string_scanner::read_double(void) { double d; read(d); return d; } char *string_scanner::read_charstar(void) { static char temp[300]; int i=pos, j=0; while (1) { char c=line[i]; if (c==0 || c>' ') break; i+=1; } while (1) { char c=line[i]; if (c<=' ') { temp[j]=0; break; } temp[j]=c; i+=1; j+=1; } pos=i; ok=temp[0]!=0; return temp; } string string_scanner::read_string(void) { char *t=read_charstar(); return string(t); } void string_scanner::read(string &s) { char *t=read_charstar(); s=string(t); } void string_scanner::read(void) { } void string_scanner::close(void) { } char *string_scanner::read_line(void) { return line+pos; } StringWriter::StringWriter(int sz) { size=sz; incr=sz; p=0; resizable=1; if (size==0) s=NULL; else s=new char[size+1]; } StringWriter::StringWriter(char *inits, int sz) { size=sz-1; incr=0; p=0; resizable=0; s=inits; } StringWriter::~StringWriter(void) { if (resizable && size!=0) delete[] s; } char *StringWriter::Close(void) { flush(); size=0; p=0; return s; } void StringWriter::Reset(void) { p=0; } void StringWriter::Resize(int nsz) { if (nsz<=size) return; if (!resizable) throw "Overflowing non-resizable StringWriter"; char *t=new char[nsz]; if (size!=0) { for (int i=0; i=size) Resize(p+1+incr); s[p]=c; p+=1; } void StringWriter::vaprintf(char *patt, va_list &a) { char buff[1002]; _vsnprintf(buff, 1000, patt, a); print(buff); va_end(a); } void StringWriter::printf(char *patt, ...) { va_list a; va_start(a, patt); vaprintf(patt, a); } void StringWriter::print(int n) { char b[100]; if (n<0) { print_char('-'); n=-n; } int len=0; while (1) { b[len]='0'+n%10; n=n/10; len+=1; if (n==0) break; } for (int i=len-1; i>=0; i-=1) print_char(b[i]); } void StringWriter::print(float f) { printf("%.7e", f); } void StringWriter::print(double f) { printf("%.14le", f); } void StringWriter::print(const char *str) { for (int i=0; 1; i+=1) { char c=str[i]; if (c==0) break; print_char(c); } } void StringWriter::print(const string &s) { print(s.getcstr()); } void StringWriter::newline(void) { print_char('\n'); } void StringWriter::flush(void) { if (p>=size) Resize(p+1); s[p]=0; } timer_object::timer_object(void) { look_at_the_clock(); } void timer_object::look_at_the_clock() { struct _timeb tb; _ftime(&tb); theseconds=tb.time; struct tm *t=localtime(&tb.time); thedate=19000100+(t->tm_year*10000)+(t->tm_mon*100)+(t->tm_mday); thetime=(t->tm_hour*10000)+(t->tm_min*100)+(t->tm_sec); themilliseconds=tb.millitm; } int timer_object::integer_date(void) { return thedate; } int timer_object::integer_time(void) { return thetime; } int timer_object::integer_ms(void) { return themilliseconds; } double timer_object::double_time(void) { double s=theseconds; double ms=themilliseconds; return s+ms/1000.0; } timer_object timer; void look_at_the_clock(void) { timer.look_at_the_clock(); } int integer_date(void) { return timer.integer_date(); } int integer_time(void) { return timer.integer_time(); } int integer_ms(void) { return timer.integer_ms(); } double double_time(void) { return timer.double_time(); } int randomised=0; int random(void) { int a=rand(), b=rand(), c=rand(); int r=(a + (b<<12) + (c<<24)) & 0x7fffffff; return r; } void randomise(void) { randomised=1; struct _timeb tb; _ftime(&tb); struct tm *t=localtime(&tb.time); srand(tb.millitm+t->tm_sec*1000+t->tm_min*60000); } void randomize(void) { randomise(); } void do_not_randomise(void) { randomised=1; } void do_not_randomize(void) { do_not_randomise(); } int random_in_range(int a, int b) { if (!randomised) randomise(); return a+random()%(b-a+1); } float random_in_range(float a, float b) { if (!randomised) randomise(); double r=random()/2147483648.0; return (float)(a+r*(b-a)); } double random_in_range(double a, double b) { if (!randomised) randomise(); double r=random()/2147483648.0; return a+r*(b-a); } void Delay(double t) { Sleep((int)(t*1000.0)); } int Thread::numthreads=0; Thread::Thread(void) { numthreads+=1; num=numthreads; name="Thread#"; name.append(string::from_int(num)); type=0; param=0; running=0; threadfn=NULL; thread=NULL; } Thread::Thread(threadfunctionv f) { numthreads+=1; num=numthreads; name="Thread#"; name.append(string::from_int(num)); type='v'; param=0; running=0; threadfn=(void *)f; thread=NULL; } Thread::Thread(threadfunctioni f, int p) { numthreads+=1; num=numthreads; name="Thread#"; name.append(string::from_int(num)); type='i'; param=p; running=0; threadfn=(void *)f; thread=NULL; } Thread::Thread(threadfunctionvs f, void *p) { numthreads+=1; num=numthreads; name="Thread#"; name.append(string::from_int(num)); type='p'; param=(int)p; running=0; threadfn=(void *)f; thread=NULL; } void Thread::SetName(string s) { name=s; } string Thread::GetName(void) { return name; } struct clump { void *threadfn; int type, param; Thread *that; clump(void *f, int t, int p, Thread *r) { threadfn=f; type=t; param=p; that=r; } }; DWORD WINAPI startthreadfn(LPVOID pp) { clump *c=(clump *)pp; Thread *that=c->that; if (c->type==0) { that->Run(); } else if (c->type=='v') { threadfunctionv f=(threadfunctionv)c->threadfn; f(); } else if (c->type=='i') { threadfunctioni f=(threadfunctioni)c->threadfn; f(c->param); } else if (c->type=='p') { threadfunctionvs f=(threadfunctionvs)c->threadfn; f((void *)c->param); } that->running=0; threadcount-=1; return 1; } int Thread::IsRunning(void) { return running; } void Thread::Run(void) { } void Thread::Start(void) { running=1; thread=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)startthreadfn, (void *)new clump(threadfn, type, param, this), 0, &threadid); threadcount+=1; } void Thread::Start(int p) { running=1; thread=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)startthreadfn, (void *)new clump(threadfn, type, p, this), 0, &threadid); threadcount+=1; } void Thread::Start(void *p) { running=1; thread=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)startthreadfn, (void *)new clump(threadfn, type, (int)p, this), 0, &threadid); threadcount+=1; } int Semaphore::numsems=0; Semaphore::Semaphore(string n) { WaitForSingleObjectEx(semamutex,INFINITE,0); numsems+=1; num=numsems; val=0; ReleaseMutex(semamutex); if (n=="") name="Semaphore#"+num; else name=n; } void Semaphore::SetName(string s) { name=s; } string Semaphore::GetName(void) { return name; } void Semaphore::Clear(void) { WaitForSingleObjectEx(semamutex,INFINITE,0); val=0; ReleaseMutex(semamutex); } void Semaphore::Set(void) { WaitForSingleObjectEx(semamutex,INFINITE,0); val=1; ReleaseMutex(semamutex); } void Semaphore::Wait(void) { int itwas=1; while (val>0) Sleep(100); while (itwas) { WaitForSingleObjectEx(semamutex,INFINITE,0); itwas=val; if (val==0) val=1; ReleaseMutex(semamutex); } } void Semaphore::WaitUntilClearThenSet(void) { int itwas=1; while (val>0) Sleep(100); while (itwas) { WaitForSingleObjectEx(semamutex,INFINITE,0); itwas=val; if (val==0) val=1; ReleaseMutex(semamutex); } } int Semaphore::IsSet(void) { if (val==0) return 0; else return 1; } int Semaphore::IsClear(void) { if (val==0) return 1; else return 0; } char *reason=NULL; string GetReasonForFailure(void) { if (reason==NULL) return string("no failure detected"); return string(reason); } FILE *f=NULL; Image::Image(int w, int h) { width=w; height=h; pix=new int *[h]; for (int i=0; i>8)&255, (c>>16)&255); } int readthisrow=0, partstaken=0, lastbyte, remainingrep, remainingplain, atendline, atendfile, roundup; void startrow(void) { readthisrow=0; partstaken=0; remainingrep=0; remainingplain=0; atendline=0; roundup=0; } void finishrow(void) { int rem=readthisrow&3; readthisrow=0; partstaken=0; if (rem==0) return; while (rem<4) { fgetc(f); rem+=1; } } int readcolour24(void) { int b=fgetc(f); int g=fgetc(f); int r=fgetc(f); readthisrow+=3; return (r|(g<<8)|(b<<16)); } int readcolour8(void) { int c=fgetc(f); readthisrow+=1; return (ctab[c].code); } int readcolour4(void) { int c; if (partstaken==0) { lastbyte=fgetc(f); c=(lastbyte>>4)&15; readthisrow+=1; partstaken=1; } else { partstaken=0; c=lastbyte&15; } return (ctab[c].code); } int readcolour1(void) { if (partstaken==0) { lastbyte=fgetc(f); readthisrow+=1; } int c=(lastbyte>>(7-partstaken))&1; partstaken+=1; if (partstaken==8) partstaken=0; return (ctab[c].code); } int readcolour4comp(void) { int n, c; if (remainingrep>0) { partstaken&=1; if (partstaken==0) c=(lastbyte>>4)&15; else c=lastbyte&15; partstaken+=1; remainingrep-=1; return ctab[c].code; } else if (remainingplain>0) { partstaken&=1; if (partstaken==0) { lastbyte=fgetc(f); readthisrow+=1; c=(lastbyte>>4)&15; } else c=lastbyte&15; partstaken+=1; remainingplain-=1; if (remainingplain==0 && roundup) fgetc(f); return ctab[c].code; } else if (atendline || atendfile) return ctab[0].code; else { n=fgetc(f); c=fgetc(f); if (n==EOF) { atendfile=1; return 0; } if (n>0) { remainingrep=n-1; lastbyte=c; c=(lastbyte>>4)&15; partstaken=1; return ctab[c].code; } else if (n==0) { if (c==0) { atendline=1; return ctab[0].code; } else if (c==1) { atendline=1; atendfile=1; return ctab[0].code; } else if (c==2) { int dx=fgetc(f); int dy=fgetc(f); reason="Compression includes a delta"; atendline=1; atendfile=1; return 0; } else { remainingplain=c-1; roundup=(c/2)&1; lastbyte=fgetc(f); c=(lastbyte>>4)&15; partstaken=1; return ctab[c].code; } } else return ctab[0].code; } } int readcolour8comp(void) { int n, c; if (remainingrep>0) { remainingrep-=1; return ctab[lastbyte].code; } else if (remainingplain>0) { lastbyte=fgetc(f); readthisrow+=1; remainingplain-=1; if (remainingplain==0 && roundup) fgetc(f); return ctab[lastbyte].code; } else if (atendline || atendfile) return ctab[0].code; else { n=fgetc(f); c=fgetc(f); if (n==EOF) { atendfile=1; return 0; } if (n>0) { remainingrep=n-1; lastbyte=c; return ctab[lastbyte].code; } else if (n==0) { if (c==0) { atendline=1; return ctab[0].code; } else if (c==1) { atendline=1; atendfile=1; return ctab[0].code; } else if (c==2) { int dx=fgetc(f); int dy=fgetc(f); reason="Compression includes a delta"; atendline=1; atendfile=1; return 0; } else { remainingplain=c-1; roundup=c&1; lastbyte=fgetc(f); return ctab[lastbyte].code; } } else return ctab[0].code; } } Image *ImageFromFile(char *fn) { f=fopen(fn, "rb"); if (f==NULL) { reason="Can't open file"; return NULL; } if (debugbmp) printf("sizeof(BMPHeader)=%d, should be 16\n", sizeof(BMPHeader)); if (debugbmp) printf("sizeof(BMPInfoHeader)=%d, should be 40\n", sizeof(BMPInfoHeader)); BMPHeader prehdr; BMPInfoHeader hdr; int n=fread(&prehdr.letterB, 14, 1, f); if (n!=1) { reason="File too small, header missing"; return NULL; } n=fread(&hdr, 40, 1, f); if (n!=1) { reason="File too small, header missing"; return NULL; } if (prehdr.letterB!='B' || prehdr.letterM!='M') { reason="'BM' signature missing"; return NULL; } if (debugbmp) printf("File Size is %d bytes\n", prehdr.filesize); if (debugbmp) printf("Reserved for zeros is %d\n", prehdr.reserved); if (debugbmp) printf("Data Offset is %d\n", prehdr.dataoffset); if (hdr.forty!=40) { reason="size 40 missing from header"; return NULL; } int w=hdr.width, h=hdr.height, b=hdr.bitsperpixel, comp=hdr.compression, numc=hdr.numcolours; if (debugbmp) printf("width is %d pixels\n", w); if (debugbmp) printf("height is %d pixels\n", h); if (hdr.planes!=1) { reason="Number of planes is not 1"; return NULL; } if (debugbmp) printf("%d planes\n", hdr.planes); if (debugbmp) printf("%d bits per pixel\n", b); if (b!=1 && b!=4 && b!=8 && b!=24) { reason="Bits per pixel has unsupported value"; return NULL; } if (comp<0 || comp>2) { reason="Invalid compression code"; return NULL; } if (debugbmp) printf("Compression code %d\n", comp); if (debugbmp) printf("resolution %d x %d pixels per metre\n", hdr.xpixelspermetre, hdr.ypixelspermetre); if (b==1) numc=2; else if (b==8 && numc==0) numc=256; else if (b==4 && numc==0) numc=16; else if (b>8) numc=0; if (debugbmp) printf("%d colours defined\n", numc); if (debugbmp) printf("first %d colours are important\n", hdr.numimportantcolours); for (int j=0; j<256; j+=1) { ctab[j].r=0; ctab[j].g=0; ctab[j].b=0; } if (numc>(1<GetPixels(); if (comp==0) { if (b==24) { for (int row=h-1; row>=0; row-=1) { startrow(); for (int col=0; col=0; row-=1) { startrow(); for (int col=0; col=0; row-=1) { startrow(); for (int col=0; col=0; row-=1) { startrow(); for (int col=0; col=0; row-=1) { startrow(); for (int col=0; col=0; row-=1) { startrow(); for (int col=0; col=width) x=width-1; if (y>=height) y=height-1; if (x+w>width) w=width-x; if (y+h>height) h=height-y; if (w<1) w=1; if (h<1) h=1; BMPHeader h1; h1.letterB='B'; h1.letterM='M'; int bytesperline=3*w; int extraperline=(4-(bytesperline&3))&3; bytesperline+=extraperline; int filesize=54+bytesperline*h; int extrafile=(4-(filesize&3))&3; h1.filesize=filesize+extrafile; h1.reserved=0; h1.dataoffset=54; fwrite(&h1.letterB, 14, 1, f); BMPInfoHeader h2; h2.forty=40; h2.width=w; h2.height=h; h2.planes=1; h2.bitsperpixel=24; h2.compression=0; h2.imagesize=0; h2.xpixelspermetre=3936; h2.ypixelspermetre=3936; h2.numcolours=0; h2.numimportantcolours=0; fwrite(&h2, 40, 1, f); for (int yc=y+h-1; yc>=y; yc-=1) { for (int xc=x; xc>16)|(c&0xFF00)|((c&0xFF)<<16); fwrite(&v, 3, 1, f); } if (extraperline>0) { int n=0; fwrite(&n, extraperline, 1, f); } } if (extrafile>0) { int n=0; fwrite(&n, extrafile, 1, f); } } void SaveAsBMP(FILE *f, int x, int y, int w, int h) { if (mainframe==NULL) return; mainframe->SaveAsBMP(f, x, y, w, h); } void Xframe::SaveAsBMP(FILE *f) { SaveAsBMP(f, 0, 0, width, height); } void SaveAsBMP(FILE *f) { if (mainframe==NULL) return; mainframe->SaveAsBMP(f); } int Xframe::SaveAsBMP(string fn, int x, int y, int w, int h) { FILE *f=fopen(fn.getcstr(), "w"); if (f==NULL) { reason="Could not open file"; return 0; } SaveAsBMP(f, x, y, w, h); fclose(f); return 1; } int SaveAsBMP(string fn, int x, int y, int w, int h) { if (mainframe==NULL) { reason="No Graphics Window"; return 0; } return mainframe->SaveAsBMP(fn, x, y, w, h); } int Xframe::SaveAsBMP(string fn) { return SaveAsBMP(fn, 0, 0, width, height); } int SaveAsBMP(string fn) { if (mainframe==NULL) { reason="No Graphics Window"; return 0; } return mainframe->SaveAsBMP(fn); } string GetWorkingDirectory(void) { char initdir[1000]; GetCurrentDirectory(998, initdir); return string(initdir); }