Source file: /~heha/mb-iwp/RTD-RTX-Konverter.zip/src/gRTD.cpp

#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <tchar.h>
#include <shlwapi.h>
#include <shlobj.h>

// Langweile h#s-Defines. Siehe http://www.tu-chemnitz.de/~heha/hs_freeware/mein_msvc.htm
#define T(x) TEXT(x)
#define nobreak
#define elemof(x) (sizeof(x)/sizeof(*(x)))

// msvcrt-light.lib für Visual Studio 2005 sowie Gleitkommaverwendung zugänglich machen
extern "C" _CRTIMP void _cdecl __getmainargs(int*,char***,char***,void*,void*);
extern "C" void* _imp___ftol;
extern "C" _declspec(naked) int _cdecl _ftol2_sse() {_asm jmp [_imp___ftol]}
extern "C" int _fltused; int _fltused;
extern "C" _CRTIMP FILE _iob[3];
#undef stdin
#undef stdout
#undef stderr
#define stdin (_iob+0)
#define stdout (_iob+1)
#define stderr (_iob+2)


#define ghInstance (HINSTANCE)0x400000
HWND ghEdit;

void InitStruct(LPVOID p, UINT len) {
 ZeroMemory(p,len);
 *(LPDWORD)p=len;
}

/* Die Quelldatei besteht aus einem Mix aus Binär- und ASCII-Daten.
 * Die gemessenen Positionen ("Sample no" Werte) liegen in Binärform
 * als Gleitkommazahlen (Einheit "mm") vor.
 * Diese Konvertierung kopiert die Quell- zur Zieldatei, aber wandelt
 * die binären Positionsangaben in ASCII-Abweichungen um.
 * (Einheit "mm" mit 4 Nachkommastellen, also 0,1 µm, die Auflösung des
 * Laserinterferometers)
 * Diese Funktion liefert "false" bei irgendeinem Fehler; die
 * Zieldatei sollte daraufhin gelöscht werden.
 */
bool Konvertierung(LPCTSTR QuellName, LPCTSTR ZielName) {
 FILE *in,*out;
 bool ret=false;	// pessimistisch

 // Die Dateien müssen "binär" verarbeitet werden, damit nicht beim fread()
 // die 0D-0A -> 0A-Konvertierung zuschlägt und die Daten zerstört.
 in=_tfopen(QuellName,T("rb"));
 if (in) {
  out=_tfopen(ZielName,T("wb"));
  if (out) {
   char line[1024];
   float fSamples,fInterval=0;
   int iSamples=0;
   int iFlag=0;
   while (fgets(line,sizeof(line),in)) {	// Zeilen lesen (mit "\r\n" am Ende)
    fputs(line,out);	// Echo
    if (sscanf(line,"Sample no :%f",&fSamples)==1) iSamples=(int)fSamples;
    sscanf(line,"Trigger interval :%f",&fInterval);
    sscanf(line,"Flags: %d",&iFlag);
    if (strcmp(line,"Run Target Data:\r\n")==0) {
     // Ab hier kommt der Binärkram
     if (!iSamples) break;	// Fehler: keine Samplezahl im Kopfbereich
retry:
     switch (iFlag) {
      case 2: {	// RTX mit DOUBLE-Werten
       // Notwendigen Speicher anfordern
       double *adValues = new double[iSamples];
       if (!adValues) break;
       // Binärdaten in einem Stück lesen
       if (fread(adValues,sizeof(double),iSamples,in) != iSamples) break;
       // ASCII-Daten zeilenweise ausgeben
       for (int i=0; i<iSamples; i++) {	// Zeilennummer, Position oder Zeitpunkt, Abweichung
        fprintf(out,"%d\t%.4f\t%.4f\r\n",i,fInterval*i,adValues[i]);
       }
       delete[] adValues;
      }break;
      case 3: { // RTD mit SINGLE-Werten
       // Notwendigen Speicher anfordern
       float *afValues = new float[iSamples];
       if (!afValues) break;
       // Binärdaten in einem Stück lesen
       if (fread(afValues,sizeof(float),iSamples,in) != iSamples) break;
       // ASCII-Daten zeilenweise ausgeben
       for (int i=0; i<iSamples; i++) {	// Zeilennummer, Messwert, Abweichung
        fprintf(out,"%d\t%.4f\t%.4f\r\n",i,afValues[i],afValues[i]-fInterval*i);
       }
       delete[] afValues;
      }break;
      default: {	// raten anhand Datei-Restgröße (140107)
       DWORD p=ftell(in);
       fseek(in,0,SEEK_END);
       DWORD q=ftell(in)-p;
       fseek(in,p,SEEK_SET);
       if (q>=iSamples*sizeof(double)) {iFlag=2; goto retry;}
       if (q>=iSamples*sizeof(float)) {iFlag=3; goto retry;}
      }goto raus;
     }
     if (!fflush(out)) ret=true;	// jetzt kann nichts mehr passieren
    }
   }
raus:
   fclose(out);
  }
  fclose(in);
 }
 return ret;
}

// Nachricht in Editfenster ausgeben (so umständlich wirklich nötig? Scheint so…)
void _cdecl WriteMsg(LPCTSTR Line,...) {
 DWORD SelStart,SelEnd,BufLen;
 LPTSTR buf;
 BufLen=GetWindowTextLength(ghEdit)+1024;
 buf=new TCHAR[BufLen];
 BufLen=GetWindowText(ghEdit,buf,BufLen);	// Text holen
 BufLen+=wvsprintf(buf+BufLen,Line,(va_list)(&Line+1));	// Text anhängen
 lstrcpy(buf+BufLen,T("\r\n"));			// CRLF anhängen
 SendMessage(ghEdit,EM_GETSEL,(WPARAM)&SelStart,(LPARAM)&SelEnd);	// retten
 SetWindowText(ghEdit,buf);			// Text setzen
 delete[] buf;
 Edit_SetSel(ghEdit,SelStart,SelEnd);		// Selektion restaurieren
}

// Kopiert eine Datei (*.RT[DX]) durch Anhängen von ".TXT" am Dateinamen
// ins Binärformat und gibt Kommentare per WriteMsg()
void ProcessFile(LPCTSTR QuellName,FILETIME*pQuellTime) {
 TCHAR ZielName[MAX_PATH];
 WIN32_FILE_ATTRIBUTE_DATA wfads,wfadd;	// Datei-Datum Quelle und Ziel
 // Quell-Dateidatum ermitteln
 if (pQuellTime) wfads.ftLastWriteTime=*pQuellTime;
 else GetFileAttributesEx(QuellName,GetFileExInfoStandard,&wfads);
 // Ziel-Dateiname ermitteln
 lstrcpyn(ZielName,QuellName,elemof(ZielName));
 StrCatBuff(ZielName,T(".txt"),elemof(ZielName));
 // Ziel-Datei auf Existenz prüfen und Datum ermitteln sowie vergleichen
 if (GetFileAttributesEx(ZielName,GetFileExInfoStandard,&wfadd)
  && CompareFileTime(&wfads.ftLastWriteTime,&wfadd.ftLastWriteTime)<=0) {
  WriteMsg(T("Überspringe Datei %s, Zieldatei bereits vorhanden und neuer, OK"),QuellName);
 }else{
  if (Konvertierung(QuellName,ZielName)) {
   WriteMsg(T("Datei %s konvertiert nach %s: OK"),QuellName,ZielName);
  }else{
   WriteMsg(T("Konvertierung Datei %s fehlgeschlagen!"),QuellName);
   DeleteFile(ZielName);	// Eventuelles Rudiment löschen
  }
 }
}

// In akt. Verzeichnis alle *.RTD in *.RTD.TXT wandeln, sofern letztere
// nicht schon in aktuellerer Version vorhanden sind (wie make)
// OHNE Rekursion in Unterverzeichnisse
void ProcessCurrentDirectory(void) {
 HANDLE fh;
 WIN32_FIND_DATA wfd;
 bool found=false;
 fh=FindFirstFile(T("*.RTD"),&wfd);
 if (fh) {
  found=true;
  do{
   ProcessFile(wfd.cFileName,&wfd.ftLastWriteTime);
  }while (FindNextFile(fh,&wfd));
  FindClose(fh);
 }
 fh=FindFirstFile(T("*.RTX"),&wfd);
 if (fh) {
  found=true;
  do{
   ProcessFile(wfd.cFileName,&wfd.ftLastWriteTime);
  }while (FindNextFile(fh,&wfd));
  FindClose(fh);
 }
 if (!found) WriteMsg(T("Keine Renishaw .RT[DX]-Datei im Verzeichnis!"));
}

int CALLBACK BrowseCallbackProc(HWND Wnd,UINT Msg,LPARAM,LPARAM) {
 switch (Msg) {
  case BFFM_INITIALIZED: {
   WCHAR CurDir[MAX_PATH];
   GetCurrentDirectoryW(elemof(CurDir),CurDir);
   SendMessage(Wnd,BFFM_SETSELECTION,TRUE,(LPARAM)CurDir);
  }break;
 }
 return 0;
}


bool ChooseDirectory(HWND Parent, LPTSTR DirName) {
 BROWSEINFO bi={Parent,NULL,NULL,NULL,
   BIF_NEWDIALOGSTYLE|BIF_NONEWFOLDERBUTTON|BIF_RETURNONLYFSDIRS,
   BrowseCallbackProc,0,0};
 LPITEMIDLIST pidl;
 CoInitialize(NULL);
 pidl=SHBrowseForFolder(&bi);
 if (!pidl) return false;
 SHGetPathFromIDList(pidl,DirName);
 CoTaskMemFree(pidl);
 return true;
}

LRESULT CALLBACK MainWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
 switch (Msg) {
  case WM_CREATE: {
   ghEdit=CreateWindowEx(0,T("EDIT"),NULL,
     WS_CHILD|WS_VISIBLE/*|ES_READONLY*/|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_WANTRETURN|ES_NOHIDESEL|WS_VSCROLL,
     0,0,0,0,
     Wnd,(HMENU)1,ghInstance,NULL);
   WriteMsg(T("Datei oder Verzeichnis zwecks Konvertierung auswählen!"));
   WriteMsg(T("Log-Anzeige..."));
  }break;
  case WM_SIZE: {
   SetWindowPos(ghEdit,0,0,0,GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam),SWP_NOMOVE|SWP_NOZORDER);
  }break;
  case WM_COMMAND: switch (LOWORD(wParam)){
   case 101: {	// Datei öffnen
    TCHAR *Files=new TCHAR[MAX_PATH*300],*p;
    Files[0]=0;
    OPENFILENAME ofn;
    InitStruct(&ofn,sizeof(ofn));
    ofn.hwndOwner=Wnd;
    ofn.lpstrFile=Files;
    ofn.nMaxFile=MAX_PATH*300;
    ofn.lpstrFilter=T("Renishaw-RT[DX]-Dateien\0*.RTD;*.RTX\0");
    ofn.Flags=OFN_ALLOWMULTISELECT|OFN_EXPLORER|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST;
    if (GetOpenFileName(&ofn)) {
     if (SetCurrentDirectory(Files)) {	// mehrere Dateinamen angegeben...
      p=Files+lstrlen(Files)+1;		// p = erster Dateiname
      do{
       ProcessFile(p,NULL);
       p+=lstrlen(p)+1;			// nächster Dateiname
      }while(*p);
     }else{
      ProcessFile(Files,NULL);		// eine Datei konvertieren
     }
    }
    delete[] Files;
   }break;
   case 102: {
    TCHAR DirName[MAX_PATH];
    if (ChooseDirectory(Wnd,DirName)){
     SetCurrentDirectory(DirName);
     ProcessCurrentDirectory();
    }
   }break;
   case 109: SendMessage(Wnd,WM_CLOSE,0,0); break;	// beenden
   case 199: MessageBox(Wnd,T("RT[DX]-Konvertierer TU Chemnitz WZM"),T("Über gRTD"),0);
  }break;
  case WM_DESTROY: {
   PostQuitMessage(0);
  }break;
 }
 return DefWindowProc(Wnd,Msg,wParam,lParam);
}

void CALLBACK WinMainCRTStartup() {
 WNDCLASS wc={
  CS_HREDRAW|CS_VREDRAW,
  MainWndProc,
  0,0,
  ghInstance,
  LoadIcon(0,IDI_APPLICATION),
  LoadCursor(0,IDC_ARROW),
  0,
  MAKEINTRESOURCE(1),
  T("gRTD")};
 RegisterClass(&wc);
 HWND Wnd=CreateWindow(T("gRTD"),T("gRTD"),WS_OVERLAPPEDWINDOW,
   CW_USEDEFAULT,0,CW_USEDEFAULT,0,0,0,ghInstance,NULL);
 ShowWindow(Wnd,SW_SHOWDEFAULT);
 MSG Msg;
 while (GetMessage(&Msg,0,0,0)) {
  TranslateMessage(&Msg);
  DispatchMessage(&Msg);
 }
 ExitProcess((UINT)Msg.wParam);
}
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded