#include #include #include #include #include #include "library.h" #pragma warning (disable:4311) #pragma warning (disable:4312) #pragma warning (disable:4244) #pragma warning (disable:4267) const int NumberOfTextRows=36, NumberOfTextColumns=101, ScrollBackSize=1000; const char * const cppversion="library 1.04.019 (w/7) of 15th February 2006"; 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; long starttime; int killed=0; char ClassName[32]="WFMICROSOFTSUCKSQKSHXNZKAKDISUW"; int __stdcall WindowProc(HWND, unsigned, WPARAM, LPARAM); HANDLE awtevent, printmutex, semamutex, programthread; SECURITY_ATTRIBUTES secatt; HGDIOBJ blackpen=NULL; HBRUSH whitebrush=NULL, backgroundbrush=NULL, greybrush=NULL; HFONT crappydefaultfont=NULL, ansifixedfont=NULL; int lastxpos=100; int threadcount=0; void main(void); int qwqwqwignorethis=0; int time_zero=0, events_wanted=0; int defaultvisible=1; int thecount=0; int showlinenumbers=0, showtimestamps=0, showtimes=0, showtimesdates=0, lastchw=7, lastchh=16; int mousewatchx0, mousewatchx1, mousewatchy0, mousewatchy1, mousewatchstate=-1; 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 int SMcxscroll, SMcyscroll; // width/height of vertical/horizontal scroll #define XMcreate (WM_USER+1) #define XMdestroy (WM_USER+2) #define XMexit (WM_USER+3) #define XMmenu (WM_USER+20) #define XMmenu_exit (XMmenu+1) #define XMmenu_capture_text (XMmenu+2) #define XMmenu_capture_graphics (XMmenu+3) #define XMmenu_view_linenumbers (XMmenu+4) #define XMmenu_view_timestamps (XMmenu+5) #define XMmenu_view_times (XMmenu+6) #define XMmenu_view_timesdates (XMmenu+7) 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(const 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); xprintf("\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(const 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(const char *patt, ...) { va_list a; va_start(a, patt); if (logfile==NULL) { int oldlen=(int)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; } int GetEventMask(void) { return events_wanted; } void SetEventMask(int e) { events_wanted=e; } 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, int &ll) { ht=textbufferlines; wd=textlinewidth; data=textbuffer; ll=lastline; } TextOutput::TextOutput(int ht, int wd) { textbufferlines=ScrollBackSize; textlinewidth=wd; textbuffer=new char *[ScrollBackSize]; lnums=new int[ScrollBackSize]; times=new long[ScrollBackSize]; millis=new int[ScrollBackSize]; 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; char it[50], format[50]; int greywd=0; if (showlinenumbers) { sprintf(it, "%d", linecount); greywd=(int)strlen(it); sprintf(format, "%%%dd ", greywd); } else if (showtimestamps) { sprintf(it, "%.3lf", lasttimestamp-starttime); greywd=(int)strlen(it); sprintf(format, "%%%d.3lf ", greywd); } else if (showtimes) { greywd=8; } else if (showtimesdates) { greywd=19; } for (int i=0; i<=currentlinenum; i+=1) { int end=textlinewidth-1; char *thisline=textbuffer[i]; if (showlinenumbers) { fprintf(f, format, lnums[i]); } else if (showtimestamps) { fprintf(f, format, (double)times[i]-starttime+(double)millis[i]/1000.0); } else if (showtimes) { tm *tt=localtime(×[i]); if (tt==NULL) fprintf(f, " NULL "); else fprintf(f, "%2d:%02d:%02d ", tt->tm_hour, tt->tm_min, tt->tm_sec); } else if (showtimesdates) { tm *tt=localtime(×[i]); if (tt==NULL) fprintf(f, " NULL "); else fprintf(f, "%4d-%02d-%02d+%02d:%02d:%02d ", tt->tm_year+1900, tt->tm_mon+1, tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec); } for (int j=0; 1; j+=1) { char c=thisline[j]; if (c==0 || c=='\n' || c=='\r') break; c&=0x7F; fputc(c, f); } fputc('\n', f); } } void TextOutput::print_char(char c) { if (textbuffer==NULL) return; if (currentcharpos>=textlinewidth || c=='\n') { currentline[currentcharpos]=0; if (currentlinenum>=textbufferlines-1) { char *line0=textbuffer[0]; for (int i=0; irepaint(); changed=0; } if (currentcharpos==0) { lnums[currentlinenum]=linecount; _timeb tt; _ftime(&tt); times[currentlinenum]=tt.time; lasttimestamp=tt.time; millis[currentlinenum]=tt.millitm; } if (c=='\n') return; changed=1; currentline[currentcharpos]=c; currentcharpos+=1; currentline[currentcharpos]=0; } void TextOutput::repaint(void) { container->repaint(); } void TextOutput::CorrectScrollBars(int incr /* =0 */ ) { HWND hwnd=container->getHWND(); SCROLLINFO si; si.cbSize=sizeof(SCROLLINFO); si.fMask=SIF_PAGE|SIF_POS|SIF_RANGE; si.nMin=0; int max=currentlinenum; if (max<1) max=1; int pos=vstart+incr; if (pos+linesvisible>max) pos=max-linesvisible; if (pos<0) pos=0; int page=linesvisible; if (pos+page>max) page=max-pos; if (page<1) page=1; si.nMin=0; si.nMax=max; si.nPage=page; si.nPos=pos; vstart=pos; SetScrollInfo(hwnd, SB_VERT, &si, 1); si.nMin=0; max=textlinewidth; if (max<1) max=1; pos=hstart; if (pos+charsvisible>max) pos=max-charsvisible; if (pos<0) pos=0; page=charsvisible; if (pos+page>max) page=max-pos; if (page<1) page=1; si.nMin=0; si.nMax=max; si.nPage=page; si.nPos=pos; hstart=pos; SetScrollInfo(hwnd, SB_HORZ, &si, 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(const 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::xprintf(const 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 xprintf(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); void Xframe::setup(int md, int wp, int hp, char *tt, int xp, int yp, int vis, TextOutput *to) { char capt[256]; tout=to; mode=md; if (mode==AUTOMATIC_MODE) mainframe=this; if (tout!=NULL) tout->setcontainer(this); 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; fontdir=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, "%s", 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=650; else width=wp; if (hp==-1) height=500; 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(); } // -1 -1 NULL -999888 -999888 1 remove Xframe::Xframe(int wp, int hp, char *tt, int xp, int yp, int vis, TextOutput *to) { int md; if (to==NULL) md=AUTOMATIC_MODE; else md=REDRAW_MODE; setup(md, wp, hp, tt, xp, yp, vis, to); } Xframe::Xframe(const char * const md, int wp, int hp) { if (md==OFF_SCREEN) setup(ONLY_BITMAP_MODE, wp, hp, NULL, -999888, -999888, 0, NULL); else setup(AUTOMATIC_MODE, wp, hp, NULL, -999888, -999888, 1, NULL); } void BitmapCopy(int w, int h, Xframe * dst, int xd, int yd, Xframe * src, int xs, int ys, int op) { BitBlt(dst->bitmapdc, xd, yd, w, h, src->bitmapdc, xs, ys, op); if (dst->mode==AUTOMATIC_MODE) { dst->start(); BitBlt(dst->hdc, xd, yd, w, h, src->bitmapdc, xs, ys, op); dst->stop(); } } /* void TransparentBitmapCopy(int w, int h, Xframe * dst, int xd, int yd, Xframe * src, int xs, int ys, int tcol) { TransparentBlt(dst->bitmapdc, xd, yd, w, h, src->bitmapdc, xs, ys, w, h, tcol); if (dst->mode==AUTOMATIC_MODE) { dst->start(); TransparentBlt(dst->hdc, xd, yd, w, h, src->bitmapdc, xs, ys, w, h, tcol); dst->stop(); } } */ 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), backgroundbrush); 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, flags=0; if (tout!=NULL) { flags = WS_HSCROLL | WS_VSCROLL; dh+=SMcymenu+SMcyscroll; dw+=SMcxscroll; } hwnd=CreateWindow(ClassName,title, WS_OVERLAPPEDWINDOW | flags ,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, (UINT_PTR)menu, "File"); menu=CreatePopupMenu(); AppendMenu(menu, MF_STRING, XMmenu_view_linenumbers, "Line Numbers"); AppendMenu(menu, MF_STRING, XMmenu_view_timestamps, "Time Stamps"); AppendMenu(menu, MF_STRING, XMmenu_view_times, "Times"); AppendMenu(menu, MF_STRING, XMmenu_view_timesdates, "Dates and Times"); AppendMenu(menubar, MF_POPUP, (UINT_PTR)menu, "View"); 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, (UINT_PTR)menu, "Capture"); SetMenu(hwnd, menubar); DrawMenuBar(hwnd); } } void Xframe::Close(void) { if (hwnd==NULL) return; PostThreadMessage(awteventthreadid, XMdestroy, 0, (LPARAM)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; ShowWindow(hwnd, SW_SHOWDEFAULT); 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(const char *s) { char capt[256]; strcpy(capt, s); SetWindowText(hwnd, capt); } void Xframe::SetCaption(string s) { SetCaption(s.c_str()); } 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, const 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(); const char *name=nm.c_str(); HMENU menu=CreatePopupMenu(); AppendMenu(menubar, MF_POPUP, (UINT_PTR)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(const 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.c_str()); AppendMenu(menu, MF_STRING, code, nm.c_str()); 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 (int)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 (int)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); } shape::shape(void) { size=102; npts=0; xs=new double[size]; ys=new double[size]; pt=new POINT[size]; useless=new BYTE[size]; } void shape::start(double x, double y) { x0=x; y0=y; npts=0; } void shape::add(double x, double y) { if (npts>=size) { int newsz=size*2; double *nxs=new double[newsz]; double *nys=new double[newsz]; POINT *npt=new POINT[newsz]; BYTE *nus=new BYTE[newsz]; for (int i=0; iStartShape(); } void Xframe::AddVertexToShape(double x, double y) { theshape.add(x, y); } void AddVertexToShape(double x, double y) { if (mainframe==NULL) DefaultMake(); mainframe->AddVertexToShape(x, y); } void Xframe::AddHereToShape(void) { theshape.add(penx, peny); } void AddHereToShape(void) { if (mainframe==NULL) DefaultMake(); mainframe->AddHereToShape(); } void Xframe::DrawShape(void) { theshape.draw(bitmapdc, mode==AUTOMATIC_MODE ? hdc : NULL, 0, theshape.x0, theshape.y0, 1.0); } void DrawShape(void) { if (mainframe==NULL) DefaultMake(); mainframe->DrawShape(); } void Xframe::FillShape(void) { setbrush(); theshape.draw(bitmapdc, mode==AUTOMATIC_MODE ? hdc : NULL, 1, theshape.x0, theshape.y0, 1.0); } void FillShape(void) { if (mainframe==NULL) DefaultMake(); mainframe->FillShape(); } void Xframe::DrawShapeHere(void) { theshape.draw(bitmapdc, mode==AUTOMATIC_MODE ? hdc : NULL, 0, penx, peny, 1.0); } void DrawShapeHere(void) { if (mainframe==NULL) DefaultMake(); mainframe->DrawShapeHere(); } void Xframe::FillShapeHere(void) { setbrush(); theshape.draw(bitmapdc, mode==AUTOMATIC_MODE ? hdc : NULL, 1, penx, peny, 1.0); } void FillShapeHere(void) { if (mainframe==NULL) DefaultMake(); mainframe->FillShapeHere(); } void Xframe::DrawShapeScaled(double s) { theshape.draw(bitmapdc, mode==AUTOMATIC_MODE ? hdc : NULL, 0, theshape.x0, theshape.y0, s); } void DrawShapeScaled(double s) { if (mainframe==NULL) DefaultMake(); mainframe->DrawShapeScaled(s); } void Xframe::FillShapeScaled(double s) { setbrush(); theshape.draw(bitmapdc, mode==AUTOMATIC_MODE ? hdc : NULL, 1, theshape.x0, theshape.y0, s); } void FillShapeScaled(double s) { if (mainframe==NULL) DefaultMake(); mainframe->FillShapeScaled(s); } void Xframe::DrawShapeHereScaled(double s) { theshape.draw(bitmapdc, mode==AUTOMATIC_MODE ? hdc : NULL, 0, penx, peny, s); } void DrawShapeHereScaled(double s) { if (mainframe==NULL) DefaultMake(); mainframe->DrawShapeHereScaled(s); } void Xframe::FillShapeHereScaled(double s) { setbrush(); theshape.draw(bitmapdc, mode==AUTOMATIC_MODE ? hdc : NULL, 1, penx, peny, s); } void FillShapeHereScaled(double s) { if (mainframe==NULL) DefaultMake(); mainframe->FillShapeHereScaled(s); } 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); if (penw<=1) SetPixel(bitmapdc, (int)x, (int)y, penrgb); else LineTo(bitmapdc, (int)x, (int)y); if (mode==AUTOMATIC_MODE) { start(); if (penw<=1) SetPixel(hdc, (int)x, (int)y, penrgb); else 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) { if (penw<=1) SetPixel(bitmapdc, (int)penx, (int)peny, penrgb); else LineTo(bitmapdc, (int)penx, (int)peny); if (mode==AUTOMATIC_MODE) { start(); if (penw<=1) SetPixel(hdc, (int)penx, (int)peny, penrgb); else 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::DrawLineBetween(double x0, double y0, double x1, double y1) { MoveToEx(bitmapdc, (int)x0, (int)y0, NULL); LineTo(bitmapdc, (int)x1, (int)y1); if (mode==AUTOMATIC_MODE) { start(); MoveToEx(hdc, (int)x0, (int)y0, NULL); LineTo(hdc, (int)x1, (int)y1); stop(); } } void DrawLineBetween(double x0, double y0, double x1, double y1) { if (mainframe==NULL) DefaultMake(); mainframe->DrawLineBetween(x0, y0, x1, y1); } 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, const 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(const 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.c_str()); } 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, const char *fn, int fa, int fs) { SetFontFace(ff, fn); SetFontAttributes(fa); SetFontSize(fs); } void Xframe::SetFontFaceAttributesSize(const 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.c_str()); 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::SetFontDirection(double degrees) { fontdir=(int)(0.5+degrees*10.0); } Xfont MakeFont(const char * fontname, int fontattr, int fontsize, double dirdegrees) { int fontdir=(int)(0.5+dirdegrees*10.0); LOGFONT lf; MakeLogfont(lf); lf.lfHeight=-fontsize; lf.lfOrientation=fontdir; lf.lfEscapement=fontdir; 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; lf.lfPitchAndFamily&=~FIXED_PITCH; strcpy(lf.lfFaceName, fontname); HFONT f=CreateFontIndirect(&lf); if (f==NULL) f=crappydefaultfont; return f; } Xfont MakeFont(string fontname, int fontattr, int fontsize, double dirdegrees) { return MakeFont(fontname.c_str(), fontattr, fontsize, dirdegrees); } Xfont MakeFont(int fontface, int fontattr, int fontsize, double dirdegrees) { int fontdir=(int)(0.5+dirdegrees*10.0); LOGFONT lf; MakeLogfont(lf); lf.lfHeight=-fontsize; lf.lfOrientation=fontdir; lf.lfEscapement=fontdir; 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 lf.lfPitchAndFamily|=FF_MODERN; HFONT f=CreateFontIndirect(&lf); if (f==NULL) f=crappydefaultfont; return f; } void Xframe::SetFont(Xfont 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::SetFont(void) { LOGFONT lf; if (!fontchanged) return; fontchanged=0; MakeLogfont(lf); lf.lfHeight=-fontsize; lf.lfOrientation=fontdir; lf.lfEscapement=fontdir; 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::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; } Xfont Xframe::GetFont(void) { if (fontchanged) SetFont(); return currentfont; } void SetFontFace(int ff, const char *fn) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFace(ff, fn); } void SetFontFace(const char *fn) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFace(fn); } void SetFontFace(string fn) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFace(fn.c_str()); } void SetFontAttributes(int fa) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontAttributes(fa); } void SetFontSize(int fs) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontSize(fs); } void SetFontDirection(double deg) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontDirection(deg); } void SetFontFaceAttributesSize(int ff, const char *fn, int fa, int fs) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFaceAttributesSize(ff, fn, fa, fs); } void SetFontFaceAttributesSize(const 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.c_str(), fa, fs); } void SetFontFaceAttributesSize(int ff, int fa, int fs) { if (mainframe==NULL) DefaultMake(); mainframe->SetFontFaceAttributesSize(ff, fa, fs); } void SetFont(Xfont f) { if (mainframe==NULL) DefaultMake(); mainframe->SetFont(f); } Xfont GetFont(void) { if (mainframe==NULL) DefaultMake(); return mainframe->GetFont(); } void Xframe::WriteText(const char *s) { if (fontchanged) SetFont(); if (textpenrgb!=penrgb) { SetTextColor(bitmapdc, penrgb); if (mode==AUTOMATIC_MODE) { start(); SetTextColor(hdc, penrgb); stop(); } textpenrgb=penrgb; } int len=(int)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(const char *s) { if (mainframe==NULL) DefaultMake(); mainframe->WriteText(s); } void Xframe::WriteTextf(const char *patt, ...) { char tmp[1000]; va_list a; va_start(a, patt); _vsnprintf(tmp, 999, patt, a); WriteText(tmp); } void WriteTextf(const 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(const char *s, int &w, int &h) { if (fontchanged) SetFont(); SIZE sz; int len=(int)strlen(s); GetTextExtentPoint32(bitmapdc, s, len, &sz); w=sz.cx; h=sz.cy; } void Xframe::MeasureText(string s, int &w, int &h) { MeasureText(s.c_str(), 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(const 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.c_str(), 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), backgroundbrush); if (mode==AUTOMATIC_MODE) { start(); FillRect(hdc, make_rect_xywh(0,0,width,height), backgroundbrush); 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::SetBackgroundColor(int c) { if (backgroundbrush!=whitebrush) { DeleteObject(backgroundbrush); backgroundbrush=whitebrush; } backgroundrgb=c; if (backgroundrgb!=0xFFFFFF00) backgroundbrush=CreateSolidBrush(backgroundrgb); } void SetBackgroundColor(int c) { if (mainframe==NULL) DefaultMake(); mainframe->SetBackgroundColor(c); } 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); } int Xframe::PenColor(int c) { int r=penrgb; PenWidthColor(penw, c); return r; } int PenColor(int c) { if (mainframe==NULL) DefaultMake(); return 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); } int Xframe::PenWidth(int w) { int r=penw; PenWidthColor(w, penrgb); return r; } int PenWidth(int w) { if (mainframe==NULL) DefaultMake(); return mainframe->PenWidth(w); } void Xframe::Show(void) { repaint(); } void Show(void) { if (mainframe==NULL) DefaultMake(); mainframe->Show(); } void Xframe::Hide(void) { ShowWindow(hwnd, SW_HIDE); } void Hide(void) { if (mainframe==NULL) DefaultMake(); mainframe->Hide(); } void Pause(double secs) { Sleep((DWORD)(secs*1000.0+0.5)); } void PrintStats(const TEXTMETRIC &tm) { xprintf("height=%d, Ascent=%d, Descent=%d, ILead=%d, ELead=%d\n", tm.tmHeight, tm.tmAscent, tm.tmDescent, tm.tmInternalLeading, tm.tmExternalLeading); xprintf("AvWidth=%d, MaxWidth=%d, FirstChar=%d, LastChar=%d\n", tm.tmAveCharWidth, tm.tmMaxCharWidth, tm.tmFirstChar, tm.tmLastChar); xprintf("cx,cyscreen=%d,%d cx,cyfullscreen=%d,%d\n", SMcxscreen, SMcyscreen, SMcxfullscreen, SMcyfullscreen); xprintf("cx,cyicon=%d,%d cx,cysmicon=%d,%d\n", SMcxicon, SMcyicon, SMcxsmicon, SMcysmicon); xprintf("cycaption=%d, cx,cyborder=%d,%d, cx,cysizeframe=%d,%d\n", SMcycaption, SMcxborder, SMcyborder, SMcxsizeframe, SMcysizeframe); xprintf("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); SMcxscroll=GetSystemMetrics(SM_CXVSCROLL); SMcyscroll=GetSystemMetrics(SM_CYHSCROLL); SMcymenu=GetSystemMetrics(SM_CYMENU); textframe=new Xframe(800, 500, "starting", 0, 0, 1, text); SetConsoleCaption("Console: RUNNING"); try { main(); } catch (char *erm) { xprintf("\nEXCEPTION: %s\n", erm); } while (threadcount>0) Sleep(100); SetConsoleCaption("Console: PROGRAM TERMINATED"); ilog("Program main() exitted.\n"); return 1; } void Exit(int code) { if (code==0) { int ok=PostThreadMessage(awteventthreadid, XMexit, 0, 0); if (!ok) PrintLastError("Exit()"); } else { TerminateThread(programthread, code); SetConsoleCaption("Console: PROGRAM TERMINATED"); ilog("Program main() exitted.\n"); } } 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; time(&starttime); _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 (int)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); } void SetMainWindow(Xframe *f) { mainframe=f; } Xframe *GetMainWindow() { if (mainframe==NULL) DefaultMake(); return mainframe; } Xframe *GetConsoleWindow() { return textframe; } void painttextplease(Xframe *fr) { int ht, wd, maxlines, maxchars, lastline; int winw, winh, wantbuff=keyboardmode==NORMAL_MODE; char **data; fr->GetSize(winw, winh); TextOutput *tout=fr->gettext(); tout->get(maxlines, maxchars, data, lastline); 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 hstart=tout->hstart; if (hstart<0) hstart=0; int chw=currentmetric.tmAveCharWidth, chh=currentmetric.tmHeight+currentmetric.tmExternalLeading+1; if (chw==0) chw=8; if (chh==0) chh=10; lastchw=chw; lastchh=chh; int linesfittable=(winh-(wantbuff ? chh+1+5 : 1))/(chh+1); int charsfittable=(winw-6)/chw; tout->charsvisible=charsfittable-1; tout->linesvisible=linesfittable-2; wd=charsfittable+1; char it[50], format[50]; int greywd=0; if (showlinenumbers) { sprintf(it, "%d", tout->linecount); greywd=(int)strlen(it); sprintf(format, "%%%dd", greywd); } else if (showtimestamps) { sprintf(it, "%.3lf", tout->lasttimestamp-starttime); greywd=(int)strlen(it); sprintf(format, "%%%d.3lf", greywd); } else if (showtimes) { greywd=8; } else if (showtimesdates) { greywd=19; } if (wd>maxchars) wd=maxchars; ht=linesfittable; int maxx=wd*chw+9, maxy=(chh+1)*ht+1; int maxmaxy=maxy+(wantbuff ? chh+1+5 : 1); int boxx=(maxchars+greywd-hstart)*chw+9; if (greybrush==NULL) greybrush=CreateSolidBrush(0x00A0A0A0); FillRect(hdc, make_rect_xywh(0,0,maxx+100,maxmaxy), whitebrush); if (greywd!=0) FillRect(hdc, make_rect_xywh(0,0,greywd*chw+5,maxy), greybrush); MoveToEx(hdc, 0, 0, &pt); LineTo(hdc, boxx, 0); LineTo(hdc, boxx, 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+SMcxscroll+1; int newh=maxmaxy+SMcycaption+2*SMcyborder+2*SMcysizeframe+SMcymenu+SMcyscroll+1; MoveWindow(fr->getHWND(), r.left, r.top, neww, newh, 1); fr->internallysetsize(neww, newh); tout->charsvisible=(neww-6)/chw-1; tout->linesvisible=(newh-(wantbuff ? chh+1+5 : 1))/(chh+1)-2; tout->CorrectScrollBars(); tout->sized=1; } int numc=winw/chw+1; if (numc>wd) numc=wd; char ready[300]; int firstline=tout->vstart-1; // was=lastline-linesfittable+1; if (firstline<0) firstline=0; if (httextlinewidth; for (int i=0; ilastline) break; int y=(chh+1)*i; MoveToEx(hdc, 0, y, &pt); LineTo(hdc, greywd*chw+9, y); MoveToEx(hdc, boxx-5, y, &pt); LineTo(hdc, boxx, y); int ncopy=numc+15; if (ncopy>maxchars) ncopy=maxchars; int numtoprint=-1; for (int k=0; knumc || numtoprint==-1) numtoprint=numc; if (numtoprint>tlw-hstart) numtoprint=tlw-hstart; for (int kk=0; kk<15; kk+=1) ready[numtoprint+kk]=' '; if (showlinenumbers) { SetBkColor(hdc, 0x00A0A0A0); sprintf(it, format, tout->lnums[firstline+i]); TextOut(hdc, 1, y+1, it, greywd); SetBkColor(hdc, 0x00FFFFFF); TextOut(hdc, 7+greywd*chw, y+1, ready, numtoprint); } else if (showtimestamps) { SetBkColor(hdc, 0x00A0A0A0); sprintf(it, format, (double)tout->times[firstline+i]-starttime+(double)tout->millis[firstline+i]/1000.0); TextOut(hdc, 1, y+1, it, greywd); SetBkColor(hdc, 0x00FFFFFF); TextOut(hdc, 7+greywd*chw, y+1, ready, numtoprint); } else if (showtimes) { SetBkColor(hdc, 0x00A0A0A0); tm *tt=localtime(&tout->times[firstline+i]); if (tt==NULL) sprintf(it, " NULL "); else sprintf(it, "%2d:%02d:%02d", tt->tm_hour, tt->tm_min, tt->tm_sec); TextOut(hdc, 1, y+1, it, greywd); SetBkColor(hdc, 0x00FFFFFF); TextOut(hdc, 7+greywd*chw, y+1, ready, numtoprint); } else if (showtimesdates) { SetBkColor(hdc, 0x00A0A0A0); tm *tt=localtime(&tout->times[firstline+i]); if (tt==NULL) sprintf(it, " NULL "); else sprintf(it, "%4d-%02d-%02d+%02d:%02d:%02d", tt->tm_year+1900, tt->tm_mon+1, tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec); TextOut(hdc, 1, y+1, it, greywd); SetBkColor(hdc, 0x00FFFFFF); TextOut(hdc, 7+greywd*chw, y+1, ready, numtoprint); } else TextOut(hdc, 7, y+1, ready, numtoprint); for (int j=0; j299) charsfittable=299; if (charsfittable>keyboardinputlength) charsfittable=keyboardinputlength; int firstchar=0, pos=0; if (keyboardinputlength>charsfittable) { ready[0]='.'; ready[1]='.'; ready[2]='.'; pos=3; firstchar=keyboardinputlength-charsfittable+3; } int len=keyboardinputlength; for (i=firstchar; i<=keyboardinputlength; i+=1) { char c=keyboardinput[i]; if (c==0) break; if (c==10) c=17; ready[pos]=c; pos+=1; } if (wantbuff) { for (int i=0, where=5; isavein(savf); fclose(savf); char msg[1000]; sprintf(msg, "Console text saved in\n %s", fn.c_str()); MessageBox(NULL, msg, "Text Output Saved", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); } } return 0; } case XMmenu_view_linenumbers: { showlinenumbers=!showlinenumbers; showtimestamps=0; showtimes=0; showtimesdates=0; fr->repaint(); return 0; } case XMmenu_view_timestamps: { showlinenumbers=0; showtimestamps=!showtimestamps; showtimes=0; showtimesdates=0; fr->repaint(); return 0; } case XMmenu_view_times: { showlinenumbers=0; showtimestamps=0; showtimes=!showtimes; showtimesdates=0; fr->repaint(); return 0; } case XMmenu_view_timesdates: { showlinenumbers=0; showtimestamps=0; showtimes=0; showtimesdates=!showtimesdates; fr->repaint(); 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.c_str(), "w"); if (savf==NULL) { char err[1000]; sprintf(err, "Could not create file:\n %s", fn.c_str()); 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.c_str()); 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 { xprintf("uncaught WM_COMMAND %d\n", item); log("uncaught WM_COMMAND %d\n", item); } } } break; } case WM_VSCROLL: { if (fr==textframe) { SCROLLINFO si; int redraw=0, setpos=1; si.cbSize=sizeof(SCROLLINFO); si.fMask=SIF_ALL; GetScrollInfo(window, SB_VERT, &si); int pos=si.nPos; switch (LOWORD(wparam)) { case SB_LINEUP: pos-=1; redraw=1; break; case SB_LINEDOWN: pos+=1; redraw=1; break; case SB_PAGEUP: pos-=text->linesvisible-2; redraw=1; break; case SB_PAGEDOWN: pos+=text->linesvisible-2; redraw=1; break; case SB_THUMBPOSITION: pos=si.nTrackPos; break; case SB_THUMBTRACK: pos=si.nTrackPos; break; case SB_TOP: pos=0; break; case SB_BOTTOM: pos=text->currentlinenum-text->linesvisible+2; break; case SB_ENDSCROLL: redraw=1; setpos=0; break; } if (setpos) text->vstart=pos; si.fMask=SIF_POS; si.nPos=pos; SetScrollInfo(window, SB_VERT, &si, redraw); text->repaint(); return 0; } break; } case WM_HSCROLL: { if (fr==textframe) { SCROLLINFO si; int redraw=0, setpos=1; si.cbSize=sizeof(SCROLLINFO); si.fMask=SIF_ALL; GetScrollInfo(window, SB_HORZ, &si); int pos=si.nPos; switch (LOWORD(wparam)) { case SB_LINELEFT: pos-=1; redraw=1; break; case SB_LINERIGHT: pos+=1; redraw=1; break; case SB_PAGELEFT: pos-=text->charsvisible-2; redraw=1; break; case SB_PAGERIGHT: pos+=text->charsvisible-2; redraw=1; break; case SB_THUMBPOSITION: pos=si.nTrackPos; break; case SB_THUMBTRACK: pos=si.nTrackPos; break; case SB_LEFT: pos=0; break; case SB_RIGHT: pos=text->textlinewidth-text->charsvisible+2; break; case SB_ENDSCROLL: redraw=1; setpos=0; break; } if (setpos) text->hstart=pos; si.fMask=SIF_POS; si.nPos=pos; SetScrollInfo(window, SB_HORZ, &si, redraw); text->repaint(); return 0; } 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 XMexit: { xprintf("XMexit received\n"); TerminateThread(programthread,1); killed=1; PostQuitMessage(1); return 0; } 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_SYSKEYUP: { break; } case WM_SYSKEYDOWN: { break; } case WM_SYSCHAR: { break; } case WM_KEYUP: { break; } case WM_KEYDOWN: { 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: { 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: { break; } { if (fr==textframe || mousewatchstate==-1) break; int x=LOWORD(lparam); int y=HIWORD(lparam); int inside=(x>=mousewatchx0 && x<=mousewatchx1 && y>=mousewatchy0 && y<=mousewatchy1); if (mousewatchstate==0) { mousewatchstate=1+inside; break; } if (mousewatchstate==1) { if (inside) { register_event(MOUSE_MOVED_INSIDE, x, y, fr); mousewatchstate=-1; } break; } if (mousewatchstate==2) { if (!inside) { register_event(MOUSE_MOVED_OUTSIDE, x, y, fr); mousewatchstate=-1; } break; } } case WM_ERASEBKGND: { if (fr->istext()) break; return 1; } case WM_PAINT: { 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; if (fr->istext()) { dh+=SMcyscroll; dw+=SMcxscroll; } int w=r.right-r.left-dw, h=r.bottom-r.top-dh; fr->internallysetsize(w, h); fr->setpaintDC(hdc); fr->autopaint(); fr->setpaintDC(NULL); ReleaseDC(window,hdc); EndPaint(window,&ps); 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: { if (fr==textframe) break; int x=LOWORD(lparam); int y=HIWORD(lparam); if (events_wanted & MOUSE_MOVEMENT) register_event(MOUSE_MOVEMENT, x, y, fr); if (mousewatchstate==-1) break; int inside=(x>=mousewatchx0 && x<=mousewatchx1 && y>=mousewatchy0 && y<=mousewatchy1); if (mousewatchstate==0) { mousewatchstate=1+inside; break; } if (mousewatchstate==1) { if (inside) register_event(MOUSE_MOVED_INSIDE, x, y, fr); break; } if (mousewatchstate==2) { if (!inside) register_event(MOUSE_MOVED_OUTSIDE, x, y, fr); break; } 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; } if (fr==textframe) log("w=%d h=%d lastchw=%d lastchh=%d\n", w, h, lastchw, lastchh); fr->ongoingw=w; fr->ongoingh=h; if (fr==textframe) text->CorrectScrollBars(); 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); } if (fr==textframe) text->CorrectScrollBars(); 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 sneak_char_if_ready(void) { if (keyboardinputlength==0) return 0; return keyboardinput[0]; } 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 WaitForMousePress(int &x0, int &y0) { int x1, y1, 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; } } int DontWaitForMouseEventOrKeyPress(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; return 1; } return 0; } 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 sneak_char(void) { SetConsoleCaption("Console: WAITING FOR INPUT"); while (newlinesinbuffer==0 && !killed) Sleep(100); SetConsoleCaption("Console: RUNNING"); return sneak_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) { xprintf("%.7f", f); } void print(double f) { xprintf("%.14lf", f); } void print_sci(int n) { xprintf("%.9le", (double)n); } void print_sci(float f) { xprintf("%.7e", f); } void print_sci(double f) { xprintf("%.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; } 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(float f) { if (ofile!=NULL) fprintf(ofile, "%.7f", f); } void output_object::print(double f) { if (ofile!=NULL) fprintf(ofile, "%.14lf", f); } void output_object::print_sci(int n) { if (ofile!=NULL) fprintf(ofile, "%.9le", (double)n); } void output_object::print_sci(float f) { if (ofile!=NULL) fprintf(ofile, "%.7e", f); } void output_object::print_sci(double f) { if (ofile!=NULL) fprintf(ofile, "%.14le", 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.c_str(), 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(const 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) { const char *fname=filename.c_str(); 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(const 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) { const char *fname=filename.c_str(); 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; const char *t=s.c_str(); len=strlen(t); if (len>256) len=256; strncpy(line,t,257); if (line[len-1]=='\n') { len-=1; line[len]=0; } 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("%.7f", f); } void StringWriter::print(double f) { printf("%.14lf", f); } void StringWriter::print_sci(int n) { printf("%.9le", (double)n); } void StringWriter::print_sci(float f) { printf("%.7e", f); } void StringWriter::print_sci(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.c_str()); } 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(); } 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); } int dummyint=0; int int_from_string(const char *s, int &ok /* =dummyint */) { int n=strlen(s), pos=0, sign=1, value=0; while (pos'9') { ok=0; return 0; } while (pos='0' && s[pos]<='9') { value=value*10+s[pos]-'0'; pos+=1; } while (postm_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; } void Thread::Stop(void) { TerminateThread(thread, 1); running=0; 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(const char *fn) { f=fopen(fn, "rb"); if (f==NULL) { reason="Can't open file"; return NULL; } if (debugbmp) xprintf("sizeof(BMPHeader)=%d, should be 16\n", sizeof(BMPHeader)); if (debugbmp) xprintf("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) xprintf("File Size is %d bytes\n", prehdr.filesize); if (debugbmp) xprintf("Reserved for zeros is %d\n", prehdr.reserved); if (debugbmp) xprintf("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) xprintf("width is %d pixels\n", w); if (debugbmp) xprintf("height is %d pixels\n", h); if (hdr.planes!=1) { reason="Number of planes is not 1"; return NULL; } if (debugbmp) xprintf("%d planes\n", hdr.planes); if (debugbmp) xprintf("%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) xprintf("Compression code %d\n", comp); if (debugbmp) xprintf("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) xprintf("%d colours defined\n", numc); if (debugbmp) xprintf("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.c_str(), "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); } int GetTextFromClipboard(string &s) { int k=OpenClipboard(NULL); if (!k) return 0; HANDLE h=GetClipboardData(CF_TEXT); if (!h) { CloseClipboard(); return 0; } char *c=(char *)GlobalLock(h); if (!c) { GlobalUnlock(h); CloseClipboard(); return 0; } s=string(c); GlobalUnlock(h); CloseClipboard(); return 1; } int SendTextToClipboard(string s) { int k=OpenClipboard(NULL); if (!k) return 0; const char *c=s.c_str(); int len=strlen(c); HANDLE h=GlobalAlloc(GMEM_DDESHARE, len+1); if (!h) { CloseClipboard(); return 0; } char *cc=(char *)GlobalLock(h); strcpy(cc, c); GlobalUnlock(h); SetClipboardData(CF_TEXT, h); CloseClipboard(); return 1; } const char ios::scientific='s'; const char ios::fixed='f'; const char ios::left='l'; const char ios::right='r'; manipulator setw(int n) { return manipulator('w', n); } manipulator setprecision(int n) { return manipulator('p', n); } manipulator setiosflags(char k) { return manipulator(k, 0); } void ostream::init(const char *fn) { ok=false; ateof=true; scient=false; rjust=false; width=0; precis=0; if (fn==NULL) ok=true; else { f=fopen(fn, "w"); if (f!=NULL) ok=true; } alive=ok; } ostream::ostream(const char *fn) { init(fn); } ostream::ostream(const string fn) { init(fn.c_str()); } ostream::ostream(const ostream &os) { f=os.f; strcpy(format, os.format); ok=os.ok; ateof=os.ateof; scient=os.scient; rjust=os.rjust; width=os.width; precis=os.precis; alive=os.alive; } ostream::ostream(void) { init(NULL); } bool ostream::fail(void) { return !ok; } bool ostream::eof(void) { return ateof; } void ostream::clear(void) { ok=true; } void ostream::close(void) { if (f!=NULL) { fclose(f); f=NULL; } ok=false; alive=false; } ostream & ostream::operator << (const manipulator m) { if (!ok || !alive) return *this; if (m.kind=='w') width=m.data; else if (m.kind=='p') precis=m.data; else if (m.kind=='s') scient=true; else if (m.kind=='f') scient=false; else if (m.kind=='r') rjust=true; else if (m.kind=='l') rjust=false; return *this; } void ostream::doformat(char kind) { strcpy(format, "%"); int flen=1; if (rjust) { strcat(format, "-"); flen+=1; } if (width>0) { sprintf(format+flen, "%d", width); flen=strlen(format); } if (precis>0 && (kind=='f' || kind=='d')) { sprintf(format+flen, ".%d", precis); flen=strlen(format); } if (kind=='i') strcpy(format+flen, "d"); else if (kind=='c') strcpy(format+flen, "c"); else if (kind=='s') strcpy(format+flen, "s"); else if (kind=='f') if (scient) strcpy(format+flen, "e"); else strcpy(format+flen, "f"); else if (kind=='d') if (scient) strcpy(format+flen, "le"); else strcpy(format+flen, "lf"); width=0; } ostream & ostream::operator << (const int m) { if (!ok || !alive) return *this; doformat('i'); if (f==NULL) xprintf(format, m); else fprintf(f, format, m); return *this; } ostream & ostream::operator << (const char m) { if (!ok || !alive) return *this; doformat('c'); if (f==NULL) xprintf(format, m); else fprintf(f, format, m); return *this; } ostream & ostream::operator << (const float m) { if (!ok || !alive) return *this; doformat('f'); if (f==NULL) xprintf(format, m); else fprintf(f, format, m); return *this; } ostream & ostream::operator << (const double m) { if (!ok || !alive) return *this; doformat('d'); if (f==NULL) xprintf(format, m); else fprintf(f, format, m); return *this; } ostream & ostream::operator << (const string m) { if (!ok || !alive) return *this; doformat('s'); if (f==NULL) xprintf(format, m.c_str()); else fprintf(f, format, m.c_str()); return *this; } ostream & ostream::operator << (const char * m) { if (!ok || !alive) return *this; doformat('s'); if (f==NULL) xprintf(format, m); else fprintf(f, format, m); return *this; } ostream cout; void istream::init(const char *fn) { ok=false; ateof=false; alreadygot=false; skipgot=0; it=new char[300]; itlen=300; if (fn==NULL) ok=true; else { f=fopen(fn, "r"); if (f!=NULL) ok=true; } alive=ok; } istream::istream(const char *fn) { init(fn); } istream::istream(const string fn) { init(fn.c_str()); } istream::istream(const istream &is) { f=is.f; ok=is.ok; ateof=is.ateof; if (is.alreadygot) { itlen=is.itlen; it=new char[itlen]; strcpy(it, is.it); } else { it=new char[300]; itlen=300; } skipgot=is.skipgot; alive=is.alive; } istream::istream(void) { init(NULL); } bool istream::fail(void) { return !ok; } bool istream::eof(void) { return ateof; } void istream::clear(void) { ok=true; } void istream::close(void) { if (f!=NULL) { fclose(f); f=NULL; } delete[] it; ok=false; alive=false; } void istream::getone(void) { if (!ok || !alive) return; if (alreadygot) { alreadygot=false; if (it[skipgot]!=0) return; } skipgot=0; it[0]=0; int len=0, c; while (true) { if (f==NULL) c=read_char(); else c=fgetc(f); if (c==EOF || c>' ') break; } if (c==EOF) { ateof=true; ok=false; return; } while (true) { if (len>=itlen-1) { char *newit=new char[itlen+300]; strcpy(newit, it); delete[] it; it=newit; itlen+=300; } it[len]=c; len+=1; if (f==NULL) c=read_char(); else c=fgetc(f); if (c<=' ') break; } it[len]=0; } istream & istream::operator >> (int & m) { if (!ok || !alive || ateof) return *this; getone(); if (!ok) return *this; char *ptr=NULL; int val=strtol(it+skipgot, &ptr, 10); if (*ptr==0) m=val; else { ok=false; alreadygot=true; } return *this; } istream & istream::operator >> (char & m) { if (!ok || !alive || ateof) return *this; getone(); if (!ok) return *this; m=it[skipgot]; alreadygot=true; skipgot+=1; return *this; } istream & istream::operator >> (float & m) { if (!ok || !alive || ateof) return *this; getone(); if (!ok) return *this; char *ptr=NULL; double val=strtod(it, &ptr); if (*ptr==0) m=(float)val; else { ok=false; alreadygot=true; } return *this; } istream & istream::operator >> (double & m) { if (!ok || !alive || ateof) return *this; getone(); if (!ok) return *this; char *ptr=NULL; double val=strtod(it, &ptr); if (*ptr==0) m=val; else { ok=false; alreadygot=true; } return *this; } istream & istream::operator >> (string & m) { if (!ok || !alive || ateof) return *this; getone(); if (!ok) return *this; m=it; return *this; } istream & istream::operator >> (char * m) { if (!ok || !alive || ateof) return *this; getone(); if (!ok) return *this; strcpy(m, it); return *this; } istream cin; #undef getchar int getchar(void) { return read_char(); } #undef putchar int putchar(int c) { print_char(c); return c; } char i_sneak(FILE *f) { if (f==stdin) return sneak_char(); else { int c=fgetc(f); ungetc(c, f); return c; } } char i_get(FILE *f) { if (f==stdin) return read_char(); else return fgetc(f); } void i_skipspc(FILE *f, char &c) { while (c>=0 && c<=' ') { c=i_get(f); c=i_sneak(f); } } int i_getstuff(FILE *f, char *buff, int max, int flt, char &c) { int len=0, hade=0, hadpt=0, digs=0; char prev=0; while (1) { if (len>=max) break; if (len==0 && (c=='+' || c=='-')) { buff[len]=c; len+=1; c=i_get(f); c=i_sneak(f); } else if (c>='0' && c<='9') { if (!hade) digs+=1; buff[len]=c; len+=1; c=i_get(f); c=i_sneak(f); } else if (c=='.' && flt && !hade && !hadpt) { hadpt=1; buff[len]=c; len+=1; c=i_get(f); c=i_sneak(f); } else if ((c=='e' || c=='E') && flt && !hade) { hade=1; buff[len]=c; len+=1; c=i_get(f); c=i_sneak(f); if ((c=='+' || c=='-') && len0; } int i_fscanf(FILE *fil, const char *fmt, va_list va) { int ptr=0, nok=0, num=0, ell=0; char buff[1000]; char c=i_sneak(fil); for (int i=0; c!=EOF; i+=1) { char f=fmt[i]; if (f==0) break; if (f==' ') { i_skipspc(fil, c); continue; } if (f!='%') { if (c!=f) break; c=i_get(fil); c=i_sneak(fil); continue; } num=0; i+=1; f=fmt[i]; while (f>='0' && f<='9') { num=num*10+f-'0'; i+=1; f=fmt[i]; } ell=0; if (f=='l') { ell=1; i+=1; f=fmt[i]; } if (num==0) num=999; if (f=='d') { i_skipspc(fil, c); int ok=i_getstuff(fil, buff, num, 0, c); if (!ok) return nok; int *p=va_arg(va, int *); *p=atol(buff); nok+=1; } else if (f=='f') { i_skipspc(fil, c); int ok=i_getstuff(fil, buff, num, 1, c); if (!ok) return nok; if (ell) { double *p=va_arg(va, double *); *p=atof(buff); } else { float *p=va_arg(va, float *); *p=(float)atof(buff); } nok+=1; } else if (f=='c') { char *p=va_arg(va, char *); if (num==999) num=1; for (int j=0; jGetSize(w, h); tc=new int[w]; bc=new int[w]; lc=new int[h]; rc=new int[h]; set(l, t, r, b); draw(); } void temporary_rectangle::set(int l, int t, int r, int b) { if (l<=r) { left=l; right=r; } else { left=r; right=l; } if (t<=b) { top=t; bot=b; } else { top=b; bot=t; } if (left<0) left=0; if (right<0) right=0; if (top<0) top=0; if (bot<0) bot=0; int w, h; fr->GetSize(w, h); if (left>=w) left=w-1; if (right>=w) right=w-1; if (top>=h) top=h-1; if (bot>=h) bot=h-1; } temporary_rectangle::~temporary_rectangle(void) { undraw(); delete[] tc; delete[] bc; delete[] lc; delete[] rc; } void temporary_rectangle::draw(void) { for (int x=left; x<=right; x+=1) { tc[x]=fr->GetPixelColor(x, top); bc[x]=fr->GetPixelColor(x, bot); } for (int y=top; y<=bot; y+=1) { lc[y]=fr->GetPixelColor(left, y); rc[y]=fr->GetPixelColor(right, y); } fr->DrawRectangleXYXY(left, top, right, bot); } void temporary_rectangle::undraw(void) { for (int x=left; x<=right; x+=1) { fr->ColorPixel(x, top, tc[x]); fr->ColorPixel(x, bot, bc[x]); } for (int y=top; y<=bot; y+=1) { fr->ColorPixel(left, y, lc[y]); fr->ColorPixel(right, y, rc[y]); } } void temporary_rectangle::change(int l, int t, int r, int b) { undraw(); set(l, t, r, b); draw(); } Region GetDrag(Xframe * f) { int e, x, y, t, c, down=0, maxx=0, maxy=0; Region r; temporary_rectangle * tr=NULL; int oe=GetEventMask(); SetEventMask(MOUSE_PRESS_L | MOUSE_RELEASE_L | MOUSE_MOVEMENT); while (1) { WaitAndGetNextEvent(e, x, y, t, c); if (e==MOUSE_PRESS_L) { r.left=x; r.top=y; tr=new temporary_rectangle(x, y, x, y, f); down=1; } else if (down && e==MOUSE_MOVEMENT && x>=r.left && y>=r.top) { PenColor(PEN_WHITE); if (tr==NULL) { r.left=x; r.top=y; tr=new temporary_rectangle(x, y, x, y, f); down=1; } else tr->change(r.left, r.top, x, y); } else if (e==MOUSE_RELEASE_L) { r.right=x; r.bottom=y; if (tr!=NULL) delete tr; down=0; break; } } SetEventMask(oe); return r; } Region Xframe::GetDrag(void) { return ::GetDrag(this); } double sqrt(int x) { return sqrt((double)x); } double pow(int x, double y) { return pow((double)x, y); } double exp(int x) { return exp((double)x); } double log(int x) { return log((double)x); } double log10(int x) { return log10((double)x); } double sin(int x) { return sin((double)x); } double cos(int x) { return cos((double)x); } double tan(int x) { return tan((double)x); } double asin(int x) { return asin((double)x); } double acos(int x) { return acos((double)x); } double atan(int x) { return atan((double)x); } double atan2(int x, int y) { return atan2((double)x, (double)y); } double atan2(double x, int y) { return atan2(x, (double)y); } double atan2(int x, double y) { return atan2((double)x, y); }