diff options
author | Piotr Strzelczyk <piotr@eps.gda.pl> | 2011-06-07 22:42:20 +0000 |
---|---|---|
committer | Piotr Strzelczyk <piotr@eps.gda.pl> | 2011-06-07 22:42:20 +0000 |
commit | b8dfbc9c6b54d6976e2d0ae38049c23c618afeed (patch) | |
tree | 86d6272c4b441476a273a12252228c4936fa0bb4 /Build/source/texk | |
parent | 22a39f77a28f39b600112e5c375ec9e50336d508 (diff) |
configurable tl-tray-menu + example configuration file
git-svn-id: svn://tug.org/texlive/trunk@22856 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk')
-rw-r--r-- | Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c | 403 |
1 files changed, 235 insertions, 168 deletions
diff --git a/Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c b/Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c index b848b223898..a9281fd2223 100644 --- a/Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c +++ b/Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c @@ -18,223 +18,290 @@ gcc -Os -s -mwindows -o tl-tray-menu.exe tl-tray-menu-rc.o tl-tray-menu.c #include <stdlib.h> #include <stdio.h> -#define MAX_CMD 32768 +#define MAX_STR 32768 + +static char strBuf[MAX_STR]; -static char msgbuf[4*MAX_PATH]; #define DIE(...) { \ - _snprintf( msgbuf, 4*MAX_PATH, __VA_ARGS__ ); \ - MessageBox( NULL, msgbuf, "ERROR!", MB_ICONERROR | MB_SETFOREGROUND );\ + _snprintf( strBuf, 4*MAX_PATH, __VA_ARGS__ ); \ + MessageBox( NULL, strBuf, "ERROR!", MB_ICONERROR | MB_SETFOREGROUND );\ return 1; \ } #define IDI_ICON 1 // resource number of icon #define IDI_TRAY 100 #define WM_TRAYMSG 101 -#define MENU_TLMGR 0 -#define MENU_TEXDOC 1 -#define MENU_EDITOR 2 -#define MENU_COMSPEC 3 -#define MENU_CUSTOM 4 -#define MENU_EXIT 42 -HMENU hPopMenu; -NOTIFYICONDATA nid; +#define MAX_MENU_ENTRIES 31 +#define MENU_CONFIG ( MAX_MENU_ENTRIES + 1 ) +#define MENU_EXIT ( MAX_MENU_ENTRIES + 2 ) -char szAppName[] = "TrayMenu"; -char ExeList[5][MAX_PATH] = { - "tlmgr-gui.exe", - "texdoctk.exe", - "texworks.exe", - "cmd.exe", - "" -}; +// buffer holding menu labels and commands +// (used only with config file) +static char menuStrings[MAX_STR]; -int CustomHowMessageBox() -{ -} +// default menu labels +char *menuLabels[MAX_MENU_ENTRIES] = { +"&Package Manager", +"&Documentation", +"&Editor", +"&Command Prompt", +NULL }; + +// default menu commands +char *menuCommands[MAX_MENU_ENTRIES] = { +"bin\\win32\\tlmgr-gui.exe", +"bin\\win32\\texdoctk.exe", +"bin\\win32\\texworks.exe", +"tlpkg\\installer\\tl-cmd.bat", +NULL }; + +char configInfo[4*MAX_PATH] = "\ +The menu can be customized with a configuration file.\n\ +For an example and instructions see:\n"; + +HMENU hPopMenu; +NOTIFYICONDATA nid; LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch ( msg ) { - case WM_CREATE: - { - hPopMenu = CreatePopupMenu(); - if ( ExeList[MENU_TLMGR][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_TLMGR, "&Package Manager (tlmgr)" ); - if ( ExeList[MENU_TEXDOC][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_TEXDOC, "&Documentation (texdoc)" ); - if ( ExeList[MENU_EDITOR][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_EDITOR, "&Editor (texworks)" ); - if ( ExeList[MENU_COMSPEC][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_COMSPEC, "&Command Prompt" ); - if ( ExeList[MENU_CUSTOM][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_CUSTOM, "Custom &Script" ); - else - AppendMenu( hPopMenu, MF_SEPARATOR, 0, NULL ); - AppendMenu( hPopMenu, MF_STRING, MENU_EXIT, "E&xit" ); - } - break; - - case WM_TRAYMSG: - { - switch ( lParam ) + case WM_CREATE: { - case WM_LBUTTONUP: - case WM_RBUTTONUP: + hPopMenu = CreatePopupMenu(); + int i; + for ( i = 0; menuLabels[i]; i++ ) { - POINT pnt; - GetCursorPos( &pnt ); - SetForegroundWindow( hWnd ); // needed to get keyboard focus - TrackPopupMenu( hPopMenu, TPM_LEFTALIGN, pnt.x, pnt.y, TPM_LEFTBUTTON, hWnd, NULL ); + if ( menuCommands[i] ) + AppendMenu( hPopMenu, MF_STRING, i, menuLabels[i] ); } - break; + AppendMenu( hPopMenu, MF_SEPARATOR, 0, NULL ); + AppendMenu( hPopMenu, MF_STRING, MENU_CONFIG, "More..." ); + AppendMenu( hPopMenu, MF_STRING, MENU_EXIT, "E&xit" ); } - } - break; - - case WM_COMMAND: - switch ( LOWORD( wParam ) ) + break; + + case WM_TRAYMSG: { - case MENU_TLMGR: - case MENU_TEXDOC: - case MENU_EDITOR: - case MENU_COMSPEC: - if ( _spawnlp( _P_NOWAIT, ExeList[LOWORD(wParam)], NULL ) < 0 ) - DIE( "Failed to start: %s", ExeList[LOWORD(wParam)] ); - break; - case MENU_CUSTOM: - if ( GetFileAttributes( ExeList[LOWORD(wParam)] ) != INVALID_FILE_ATTRIBUTES ) - { - if ( _spawnlp( _P_NOWAIT, ExeList[LOWORD(wParam)], NULL ) < 0 ) - DIE( "Failed to start: %s", ExeList[LOWORD(wParam)] ); - } - else - MessageBox( - NULL, - "For a custom menu, create tl-tray-menu-custom.bat \nin the root of the installation.\nSee sample at tlpkg\\installer\\tl-tray-menu-custom.bat.", - "Custom menu", - MB_ICONINFORMATION - ); - break; - - case MENU_EXIT: - Shell_NotifyIcon( NIM_DELETE, &nid ); - ExitProcess(0); - break; + switch ( lParam ) + { + case WM_LBUTTONUP: + case WM_RBUTTONUP: + { + POINT pnt; + GetCursorPos( &pnt ); + SetForegroundWindow( hWnd ); // needed to get keyboard focus + TrackPopupMenu( hPopMenu, TPM_LEFTALIGN, pnt.x, pnt.y, 0, hWnd, NULL ); + } + break; + } } - break; + break; + + case WM_COMMAND: + { + switch ( LOWORD( wParam ) ) + { + case MENU_CONFIG: + MessageBox( NULL, configInfo, nid.szTip, MB_SETFOREGROUND ); + break; + + case MENU_EXIT: + Shell_NotifyIcon( NIM_DELETE, &nid ); + ExitProcess(0); + break; + + default: + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + //si.dwFlags = STARTF_USESHOWWINDOW; + //si.wShowWindow = SW_HIDE ; + ZeroMemory( &pi, sizeof(pi) ); + if( !CreateProcess( + NULL, // module name (uses command line if NULL) + menuCommands[LOWORD(wParam)], // command line + NULL, // process security atrributes + NULL, // thread security atrributes + TRUE, // handle inheritance + 0, // creation flags, e.g. CREATE_NO_WINDOW, DETACHED_PROCESS + NULL, // pointer to environment block (uses parent if NULL) + NULL, // starting directory (uses parent if NULL) + &si, // STARTUPINFO structure + &pi ) // PROCESS_INFORMATION structure + ) DIE( "Failed to execute command:\n%s", menuCommands[LOWORD(wParam)] ); + } + } + } + break; + + default: + return DefWindowProc( hWnd, msg, wParam, lParam ); - default: - return DefWindowProc( hWnd, msg, wParam, lParam ); } return 0; } int APIENTRY WinMain( - HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow ) + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow ) { + // scratch variables + + char *s; + // get file name of this executable - static char selfdir[MAX_PATH]; - char *s; - DWORD nchars = GetModuleFileName(NULL, selfdir, MAX_PATH); - if ( !nchars || ( nchars == MAX_PATH ) ) DIE( "cannot get own path" ); - if ( s = strrchr( selfdir, '\\' ) ) *s = '\0'; // remove file name part + static char dirSelf[MAX_PATH]; + DWORD nchars = GetModuleFileName(NULL, dirSelf, MAX_PATH); + if ( !nchars || ( nchars == MAX_PATH ) ) DIE( "Cannot get own path." ); + if ( s = strrchr( dirSelf, '\\' ) ) *s = '\0'; // remove file name part - // append bin/win32 to PATH + // set current directory - static char buffer[MAX_CMD]; - strcpy( buffer, selfdir ); - strcat( buffer, "\\bin\\win32;" ); - strcat( buffer, getenv( "PATH" ) ); - SetEnvironmentVariable( "PATH", buffer ); + if ( !SetCurrentDirectory( dirSelf ) ) + DIE( "Failed to change current directory to:\n%s", dirSelf ); - // set up a list of executables + // prepend bin/win32 to PATH - s = strchr( buffer, ';' ); *s = '\\'; s++; - int i; - for ( i = 0; i < 3; i++ ) - { - *s = '\0'; - strcat( buffer, ExeList[i] ); - if ( GetFileAttributes( buffer ) != INVALID_FILE_ATTRIBUTES ) - strncpy( ExeList[i], buffer, MAX_PATH ); - else - ExeList[i][0] = '\0'; - } + strcpy( strBuf, dirSelf ); + strcat( strBuf, "\\bin\\win32;" ); + strcat( strBuf, getenv( "PATH" ) ); + SetEnvironmentVariable( "PATH", strBuf ); + + // configuration + + static char fileConfig[MAX_PATH]; + s = dirSelf + strlen(dirSelf) + 1; + strcpy( fileConfig, s ); + if ( s = strrchr( fileConfig, '.' ) ) *s = '\0'; // remove file extension part + strcat( fileConfig, ".ini" ); + + strcat( configInfo, dirSelf ); + strcat( configInfo, "\\tlpkg\\installer\\" ); + strcat( configInfo, fileConfig ); - if ( s = getenv( "COMSPEC" ) ) strncpy( ExeList[3], s, MAX_PATH ); + if ( GetFileAttributes( fileConfig ) == INVALID_FILE_ATTRIBUTES ) { - strcpy( buffer, selfdir ); - strcat( buffer, "\\tl-tray-menu-custom.bat" ); - // if ( GetFileAttributes( buffer ) != INVALID_FILE_ATTRIBUTES ) - // At call time, we test for this file and display - // a message box if it is missing. - strncpy( ExeList[4], buffer, MAX_PATH ); + // validate default configuration (menuCommands should be existing files) - // create a hidden window for messaging - - MSG msg; - WNDCLASS wc; - HWND hWnd; - - ZeroMemory( &wc, sizeof wc ); - wc.hInstance = hInstance; - wc.lpszClassName = szAppName; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.style = 0; - wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); - wc.hCursor = LoadCursor( NULL, IDC_ARROW ); - - if ( FALSE == RegisterClass( &wc ) ) DIE( "Failed to register window class" ); - - hWnd = CreateWindow( - szAppName, - "", - 0, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - 0, - 0, - hInstance, - 0); - - if ( hWnd == NULL ) DIE( "Failed to create window" ); - - // tray icon stuff + int i; + for ( i = 0; menuLabels[i]; i++ ) + if ( GetFileAttributes( menuCommands[i] ) == INVALID_FILE_ATTRIBUTES ) + menuCommands[i] = NULL; + + } else { + + // read menu configuration from ini file + + FILE *CONFIG = fopen( fileConfig, "rt" ); + if ( CONFIG == NULL ) + DIE( "Failed to open configuration file:\n%s\\%s", dirSelf, fileConfig ); + + char strSect[] = "[menu]"; + int menuItem = -1; + int i = 0; + int lineNo; + for ( lineNo = 1 ; fgets( strBuf, MAX_STR, CONFIG ) + && menuItem < MAX_MENU_ENTRIES ; lineNo++ ) + { + if ( menuItem < 0 ) + { + if ( *strBuf == '[' && + strncmp( strBuf, strSect, strlen( strSect ) ) == 0 ) menuItem++; + continue; + } + if ( *strBuf == ';' ) continue; // skip comments + if ( *strBuf == '[' ) break; // next section + s = &menuStrings[i]; + i += ExpandEnvironmentStrings( strBuf, s, MAX_STR - i ); + if ( i >= MAX_STR ) + DIE( "Exceeded 32KB limit for configuration." ); + if ( i-2 && menuStrings[i-2] == '\n' ) { menuStrings[i-2] = '\0'; i--; } + menuLabels[menuItem] = s; + while ( *s && *s != '=' ) s++; + if ( *s == '\0' ) + DIE( "Missing '=' on line %d in configuration file:\n%s\\%s", + lineNo, dirSelf, fileConfig ); + *s++ = '\0'; // assign first, then increment + menuCommands[menuItem] = s; + menuItem++; + } + if ( menuItem < 0 ) + DIE( "Missing [menu] section in configuration file:\n%s\\%s", + dirSelf, fileConfig ); + menuLabels[menuItem] = NULL; + menuCommands[menuItem] = NULL; + + fclose( CONFIG ); + + } - nid.cbSize = sizeof nid; - nid.hWnd = hWnd; - nid.uID = IDI_TRAY; - nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; - nid.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_ICON ) ); - nid.uCallbackMessage = WM_TRAYMSG; - strcpy( nid.szTip, "TeX Live Menu" ); + // create a hidden window for messaging + + MSG msg; + WNDCLASS wc; + HWND hWnd; + char szAppName[] = "TrayMenu"; + + ZeroMemory( &wc, sizeof wc ); + wc.hInstance = hInstance; + wc.lpszClassName = szAppName; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.style = 0; + wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + + if ( FALSE == RegisterClass( &wc ) ) DIE( "Failed to register window class" ); + + hWnd = CreateWindow( + szAppName, + "", + 0, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + 0, + 0, + hInstance, + 0); + + if ( hWnd == NULL ) DIE( "Failed to create window" ); + + // tray icon stuff + + nid.cbSize = sizeof nid; + nid.hWnd = hWnd; + nid.uID = IDI_TRAY; + nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; + nid.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_ICON ) ); + nid.uCallbackMessage = WM_TRAYMSG; + strcpy( nid.szTip, "TeX Live Menu" ); #if (_WIN32_IE >= 0X0500) nid.uFlags |= NIF_INFO; nid.dwInfoFlags = NIIF_INFO; strcpy( nid.szInfo, "Click on the tray icon\nto activate the menu." ); strcpy( nid.szInfoTitle, nid.szTip ); #endif - Shell_NotifyIcon( NIM_ADD, &nid ); + Shell_NotifyIcon( NIM_ADD, &nid ); - // main message loop: + // main message loop: - while ( GetMessage( &msg, NULL, 0, 0 ) > 0 ) - { - TranslateMessage( &msg ); - DispatchMessage( &msg ); - } + while ( GetMessage( &msg, NULL, 0, 0 ) > 0 ) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } - return msg.wParam; + return msg.wParam; } |