/* Copyright (c) 1992, 1998, 2000, 2002, 2003, 2004, 2005, 2006 John E. Davis * This file is part of JED editor library source. * * You may distribute this file under the terms the GNU General Public * License. See the file COPYING for more information. */ #define HAS_PALETTE_CODE 0 #include "config.h" #include "jed-feat.h" #include #include #include #include "jdmacros.h" #include #include #include #include #include #include #include #include "display.h" #include "buffer.h" #include "sysdep.h" #include "screen.h" #include "keymap.h" #include "hooks.h" #include "ins.h" #include "ledit.h" #include "misc.h" #include "cmds.h" #include "sig.h" #include "win32.h" #include "colors.h" /* #include "resource.h" */ /* Where is it? */ #if JED_HAS_SUBPROCESSES # include "jprocess.h" #endif #ifdef __WIN32__ # define HAS_WHEEL_MOUSE_SUPPORT 1 #else # define HAS_WHEEL_MOUSE_SUPPORT 0 #endif #define MSW_STRING_TYPE 1 #define MSW_INT_TYPE 2 #define MSW_COLOR_TYPE 3 #define MAX_STRING_SIZE 128 #define MAX_KEYS 128 #define KEY_SHIFT 1 #define KEY_CONTROL 2 #define KEY_ALT 4 int NumLock_Is_Gold = 0; int PC_Alt_Char = 27; int PC_Fn_Char = 0; /* Last Charset used: keep track of input language changes */ static DWORD JedCharSet = DEFAULT_CHARSET; static DWORD JedACP = CP_ACP; #define SPACE_CHAR (32 | (JNORMAL_COLOR << 8)) #define MAX_MENU_ID 256 #if !defined(_MSC_VER) && !defined(__CYGWIN32__) && !defined(__MINGW32__) extern HINSTANCE _hInstance; #else HINSTANCE _hInstance; #endif #ifdef __WIN32__ HINSTANCE _hPrev; #else extern HINSTANCE _hPrev; #endif /* #define CURRENT_BG_COLOR JColors[JNORMAL_COLOR].hbrBG */ #define CURRENT_BG_COLOR This_Window.current_color->hbrBG #if HAS_WHEEL_MOUSE_SUPPORT #ifndef WM_MOUSEWHEEL # define WM_MOUSEWHEEL (WM_MOUSELAST+1) /* message that will be supported by the OS */ #endif /* Details of the mystery mouse wheel window */ #define MOUSEZ_CLASSNAME "MouseZ" /* wheel window class */ #define MOUSEZ_TITLE "Magellan MSWHEEL" /* wheel window title */ #define MSH_WHEELMODULE_CLASS (MOUSEZ_CLASSNAME) #define MSH_WHEELMODULE_TITLE (MOUSEZ_TITLE) #define MSH_MOUSEWHEEL "MSWHEEL_ROLLMSG" #define MSH_WHEELSUPPORT "MSH_WHEELSUPPORT_MSG" /* name of msg to send to query for wheel support */ #define MSH_SCROLL_LINES "MSH_SCROLL_LINES_MSG" /* Details of the mouse wheel functionality - not all currently used by Wjed */ typedef struct { HWND hwnd; UINT uiMshMsgMouseWheel, uiMshMsg3DSupport, uiMshMsgScrollLines; INT iScrollLines; BOOL fActive; } MS_Wheel_Type; static MS_Wheel_Type Wheel_Mouse; #endif /* HAS_WHEEL_MOUSE_SUPPORT */ typedef struct { char *name; int type; char *dflt; void *buf; } Msw_Ini_Type; typedef struct { COLORREF bg; COLORREF fg; HBRUSH hbrBG; } Color_Type; typedef struct { char *name; int r, g, b; } Color_Value_Type; typedef struct { char title[MAX_STRING_SIZE]; HWND w; HDC hdc; int ndc; char font_name[MAX_STRING_SIZE]; int font_height; int font_bold; int font_width; HFONT font; int x; int y; int height; int width; int scroll_r1, scroll_r2; /* scrolling region */ int cursor_row, cursor_col; /* row column of cursor (1,1) origin */ int vis_curs_row, vis_curs_col; /* position of VISIBLE cursor */ int cursor_showing; Color_Type *current_color; int focus; } MSWindow_Type; LRESULT CALLBACK JEDWndProc(HWND, UINT, WPARAM, LPARAM); static void msw_cleanup(void); static void msw_get_defaults(void); static void msw_get_default(Msw_Ini_Type *t); static void get_dc(void); static void release_dc(void); static void init_application(void); static void init_instance(void); void process_message(void); static void show_cursor(void); static void hide_cursor(void); static void msw_normal_video(void); static void set_window_name(char *s); static void msw_define_color(char *, int *, int *, int *); static void msw_select_font(char *, int *, int *); static void get_menubar(void); static void destroy_menubar(void); static void create_popup_menu(void); static void destroy_menu(void); static void append_menu_item(void); static void append_popup_menu(void); static void append_separator(void); static void insert_menu_item(void); static void insert_menu_item_pos(void); static void insert_popup_menu(void); static void insert_popup_menu_pos(void); static void insert_separator(void); static void insert_separator_pos(void); static void delete_menu_item(void); static void delete_menu_item_pos(void); static void get_menu_state(void); static void get_menu_state_pos(void); static void get_popup_menu(void); static void check_menu_item(void); static void check_menu_item_pos(void); static void enable_menu_item(void); static void enable_menu_item_pos(void); static void redraw_menubar(void); static void set_init_popup_callback(void); static void msw_help(void); static HINSTANCE hPrevInst; static HINSTANCE hInstance; static char *szJedSection = "WJED"; static int MSW_Screen_Cols; static int MSW_Screen_Rows; static int MSW_Term_Cannot_Scroll = 0; static int MSW_Term_Cannot_Insert = 0; static int MSW_Use_Ansi_Colors = 1; static int MSW_Ignore_Beep = 3; static int Performing_Update; static MSWindow_Type This_Window; static Color_Type JColors[JMAX_COLORS]; static char *InitPopup_Callback; static char *Menu_Callbacks[MAX_MENU_ID]; #if HAS_PALETTE_CODE static LPLOGPALETTE The_Lplgpl = NULL; static HPALETTE The_Hpalette = NULL; #endif static char Font_Name[MAX_STRING_SIZE]; static int Font_Height; static int Font_Bold; static Msw_Ini_Type Msw_Ini_List[] = { { "Font", MSW_STRING_TYPE, "fixed", Font_Name }, { "FontHeight", MSW_INT_TYPE, "12", &Font_Height }, { "FontBold", MSW_INT_TYPE, "-1", &Font_Bold }, { "Background", MSW_COLOR_TYPE, "0,0,0", &JColors[JNORMAL_COLOR].bg }, { "Foreground", MSW_COLOR_TYPE, "192,192,192", &JColors[JNORMAL_COLOR].fg }, { "StatusBG", MSW_COLOR_TYPE, "0,0,128", &JColors[JSTATUS_COLOR].bg }, { "StatusFG", MSW_COLOR_TYPE, "255,255,0", &JColors[JSTATUS_COLOR].fg }, { "RegionBG", MSW_COLOR_TYPE, "255,0,255", &JColors[JREGION_COLOR].bg }, { "RegionFG", MSW_COLOR_TYPE, "255,255,255", &JColors[JREGION_COLOR].fg }, { "OperatorBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JOP_COLOR].bg }, { "OperatorFG", MSW_COLOR_TYPE, "255,255,255", &JColors[JOP_COLOR].fg }, { "NumberBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JNUM_COLOR].bg }, { "NumberFG", MSW_COLOR_TYPE, "0,0,192", &JColors[JNUM_COLOR].fg }, { "StringBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JSTR_COLOR].bg }, { "StringFG", MSW_COLOR_TYPE, "0,192,255", &JColors[JSTR_COLOR].fg }, { "CommentBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JCOM_COLOR].bg }, { "CommentFG", MSW_COLOR_TYPE, "0,128,0", &JColors[JCOM_COLOR].fg }, { "KeywordBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JKEY_COLOR].bg }, { "KeywordFG", MSW_COLOR_TYPE, "255,255,255", &JColors[JKEY_COLOR].fg }, { "Keyword1BG", MSW_COLOR_TYPE, "0,0,0", &JColors[JKEY_COLOR + 1].bg }, { "Keyword1FG", MSW_COLOR_TYPE, "255,255,255", &JColors[JKEY_COLOR + 1].fg }, { "DelimiterBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JDELIM_COLOR].bg }, { "DelimiterFG", MSW_COLOR_TYPE, "255,255,255", &JColors[JDELIM_COLOR].fg }, { "PreprocessBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JPREPROC_COLOR].bg }, { "PreprocessFG", MSW_COLOR_TYPE, "0,255,0", &JColors[JPREPROC_COLOR].fg }, { "MessageBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JMESSAGE_COLOR].bg}, { "MessageFG", MSW_COLOR_TYPE, "255,255,0", &JColors[JMESSAGE_COLOR].fg}, { "ErrorFG", MSW_COLOR_TYPE, "255,0,0", &JColors[JERROR_COLOR].fg}, { "ErrorBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JERROR_COLOR].bg}, { "MenuFG", MSW_COLOR_TYPE, "0,0,0", &JColors[JMENU_COLOR].fg}, { "MenuBG", MSW_COLOR_TYPE, "0,255,255", &JColors[JMENU_COLOR].bg}, {"CursorFG", MSW_COLOR_TYPE, "0,255,0", &JColors[JCURSOR_COLOR].fg}, {"CursorBG", MSW_COLOR_TYPE, "255,0,0", &JColors[JCURSOR_COLOR].bg}, {"DollarFG", MSW_COLOR_TYPE, "0,0,255", &JColors[JDOLLAR_COLOR].fg}, {"DollarBG", MSW_COLOR_TYPE, "0,0,0", &JColors[JDOLLAR_COLOR].bg}, {"CursorOvrFG", MSW_COLOR_TYPE, "255,0,0", &JColors[JCURSOROVR_COLOR].fg}, {"CursorOvrBG", MSW_COLOR_TYPE, "0,255,0", &JColors[JCURSOROVR_COLOR].bg}, { "Title", MSW_STRING_TYPE, "WJED", This_Window.title }, { "X", MSW_INT_TYPE, "0", &This_Window.x }, { "Y", MSW_INT_TYPE, "0", &This_Window.y }, { "Width", MSW_INT_TYPE, "700", &This_Window.width }, { "Height", MSW_INT_TYPE, "500", &This_Window.height }, { NULL, 0, NULL, NULL } }; static Color_Value_Type Msw_Std_Color[] = { {"black", 0, 0, 0}, {"blue", 0, 0, 192}, {"green", 0, 128, 0}, {"cyan", 0, 192, 192}, {"red", 192, 0, 0}, {"magenta", 192, 0, 192}, {"lightgray", 192, 192, 192}, {"gray", 128, 128, 128}, {"brightblue", 0, 0, 255}, {"brightred", 255, 0, 0}, {"brightgreen", 0, 255, 0}, {"brightcyan", 0, 255, 255}, {"brightmagenta", 255, 0, 255}, {"yellow", 255, 255, 0}, {"white", 255, 255, 255}, {"brown", 110, 74, 32}, {NULL, 0, 0, 0} }; #define S SLANG_STRING_TYPE #define I SLANG_INT_TYPE static SLang_Intrin_Fun_Type Jed_WinGUI_Table[] = { MAKE_INTRINSIC_SII("w32_select_font", msw_select_font, VOID_TYPE), MAKE_INTRINSIC_S("x_set_window_name", set_window_name, VOID_TYPE), MAKE_INTRINSIC_4("w32_define_color", msw_define_color, VOID_TYPE, S,I,I,I), /*Prototype: Void msw_define_color(char *, int, int, int);*/ MAKE_INTRINSIC("w32_get_menubar", get_menubar, VOID_TYPE, 0), /* Prototype: Integer get_menubar(Void); * Returns integer which is handle of menubar. If there is no * menubar, it creates it. * To show menubar, call `redraw_menu' */ MAKE_INTRINSIC("w32_destroy_menubar", destroy_menubar, VOID_TYPE, 0), /* Prototype: Void destroy_menubar(Void); * Destroys menubar */ MAKE_INTRINSIC("w32_create_popup_menu", create_popup_menu, VOID_TYPE, 0), /* Prototype: Integer create_popup_menu(Void); * Creates empty popup menu and returns integer value which is * it's handle. If popup is not appended to another menu, it must * destroyed after use. */ MAKE_INTRINSIC("w32_destroy_menu", destroy_menu, VOID_TYPE, 0), /* Prototype: Void destroy_menu(Integer hmenu); * Destroys menu and all it's popup menus. * Note: Do not destroy menubar with this function * (use `destroy_menubar') */ MAKE_INTRINSIC("w32_append_menu_item", append_menu_item, VOID_TYPE, 0), /* Prototype: Void append_menu_item(Integer hmenu, String name, Integer id, String callback); * Appends menu item with name 'name' and identifier 'id' at the end * of 'hmenu'. When item is selected, the 'callback' will be executed. * Callback can be intrinsic or internal function. */ MAKE_INTRINSIC("w32_append_popup_menu", append_popup_menu, VOID_TYPE, 0), /* Prototype: Void append_popop_menu(Integer hmenu, String name, Integer popup); * Appends popup menu with name 'name' and handle 'popup' at the end * of 'hmenu' */ MAKE_INTRINSIC("w32_append_separator", append_separator, VOID_TYPE, 0), /* Prototype: Void append_separator(Integer hmenu); * Appends menu separator at the end of 'hmenu' */ MAKE_INTRINSIC("w32_insert_menu_item", insert_menu_item, VOID_TYPE, 0), /* Prototype: Void insert_menu_item(Integer hmenu, Integer id, String name, Integer idNew, String callback); * Inserts menu item with name 'name' and identifier 'idNew' before * menu item with identifier 'id'. * When item is selected, the 'callback' will be executed. * Callback can be intrinsic or internal function. */ MAKE_INTRINSIC("w32_insert_menu_item_pos", insert_menu_item_pos, VOID_TYPE, 0), /* Prototype: Void insert_menu_item_pos(Integer hmenu, Integer pos, String name, Integer idNew, String callback); * Inserts menu item with name 'name' and identifier 'idNew' before * menu item with zero-based position 'pos' in 'hmenu'. * When item is selected, the 'callback' will be executed. * Callback can be intrinsic or internal function. */ MAKE_INTRINSIC("w32_insert_popup_menu", insert_popup_menu, VOID_TYPE, 0), /* Prototype: Void insert_popup_menu(Integer hmenu, Integer id, String name, Integer popup); * Inserts popup menu with name 'name' and handle 'popup' before * menu item with identifier 'id' */ MAKE_INTRINSIC("w32_insert_popup_menu_pos", insert_popup_menu_pos, VOID_TYPE, 0), /* Prototype: Void insert_popup_menu_pos(Integer hmenu, Integer pos, String name, Integer popup); * Inserts popup menu with name 'name' and handle 'popup' before * menu item with zero-based position 'pos' in 'hmenu' */ MAKE_INTRINSIC("w32_insert_separator", insert_separator, VOID_TYPE, 0), /* Prototype: Void insert_separator(Integer hmenu, Integer id); * Inserts menu separator before menu item with identifier 'id' */ MAKE_INTRINSIC("w32_insert_separator_pos", insert_separator_pos, VOID_TYPE, 0), /* Prototype: Void insert_separator_pos(Integer hmenu, Integer pos); * Inserts menu separator before menu item with zero-based position 'pos' */ MAKE_INTRINSIC("w32_delete_menu_item", delete_menu_item, VOID_TYPE, 0), /* Prototype: Void delete_menu_item(Integer hmenu, Integer id); * Deletes menu item with identifier id from menu with handle 'hmenu' */ MAKE_INTRINSIC("w32_delete_menu_item_pos", delete_menu_item_pos, VOID_TYPE, 0), /* Prototype: Void delete_menu_item_pos(Integer hmenu, Integer pos); * Deletes menu item at zero-based position 'pos' from menu 'hmenu' */ MAKE_INTRINSIC("w32_get_menu_state", get_menu_state, VOID_TYPE, 0), /* Prototype: Integer get_menu_state(Integer hmenu, Integer id); * Gets state of menu item with identifier 'id' * & 1 == 1 if menu item is enabled * & 2 == 1 if menu item is checked */ MAKE_INTRINSIC("w32_get_menu_state_pos", get_menu_state_pos, VOID_TYPE, 0), /* Prototype: Integer get_menu_state(Integer hmenu, Integer pos); * Gets state of menu item at zero-based position 'pos' * & 1 == 1 if menu item is enabled * & 2 == 1 if menu item is checked */ MAKE_INTRINSIC("w32_get_popup_menu", get_popup_menu, VOID_TYPE, 0), /* Prototype: Void get_popup_menu(Integer hmenu, Integer pos); * Returns handle of popup menu at zero-based position 'pos' * If return value is 0, there is no popup at the position. */ MAKE_INTRINSIC("w32_check_menu_item", check_menu_item, VOID_TYPE, 0), /* Prototype: Void check_menu_item(Integer hmenu, Integer id, Integer flag); * This functions changes check state of menu item. If flag is nonzero, * it checks menu item, otherwise it unchecks it */ MAKE_INTRINSIC("w32_check_menu_item_pos", check_menu_item_pos, VOID_TYPE, 0), /* Prototype: Void check_menu_item(Integer hmenu, Integer pos, Integer flag); * This functions changes check state of menu item. If flag is nonzero, * it checks menu item, otherwise it unchecks it */ MAKE_INTRINSIC("w32_enable_menu_item", enable_menu_item, VOID_TYPE, 0), /* Prototype: Void check_menu_item(Integer hmenu, Integer id, Integer flag); * This functions enable or disable menu item. If flag is nonzero, the * menu item will be enabled, otherwise it'll be disabled. */ MAKE_INTRINSIC("w32_enable_menu_item_pos", enable_menu_item_pos, VOID_TYPE, 0), /* Prototype: Void check_menu_item(Integer hmenu, Integer pos, Integer flag); * This functions enable or disable menu item. If flag is nonzero, the * menu item will be enabled, otherwise it'll be disabled. */ MAKE_INTRINSIC("w32_redraw_menubar", redraw_menubar, VOID_TYPE, 0), /* Prototype: Void redraw_menubar(Void); * Redraws menubar. This functions should be called if menubar is changed */ MAKE_INTRINSIC("w32_set_init_popup_callback", set_init_popup_callback, VOID_TYPE, 0), /* Prototype: Void set_init_popup_callback(String callback); * Executes callback before menu poppup was popped up. */ MAKE_INTRINSIC("msw_help", msw_help, VOID_TYPE, 0), /* Prototype: Void msw_help(String filename, String keword, Integer Partial_Keys); * Starts Windows Help with 'filename' help file. If 'keyword' is not null * string shows topic with specified keyword. If 'Partial_Keys' != 0 * shows Search dialog if there is more than one help topic beginnig with * 'keyword' */ MAKE_INTRINSIC(NULL, NULL, 0, 0) }; #undef S #undef I static int wjed_has_unicode(void) { static int unicode = -1; if (unicode == -1) unicode = SLsmg_is_utf8_mode(); return unicode; } static void _putkey (WCHAR wc) { #if SLANG_VERSION >= 20000 if (wjed_has_unicode ()) { unsigned char buf[SLUTF8_MAX_MBLEN+1], *b; b = SLutf8_encode((SLwchar_Type)wc, buf, SLUTF8_MAX_MBLEN); buffer_keystring ((char *)buf, b-buf); } else #endif { /* 0xE0 is prefix for cursor keys, but also à on ANSI * charset. The charmap has 0xE0 0xE0 to à */ unsigned char ch = (unsigned char) wc; if (ch == 0xE0) buffer_keystring ((char *)&ch, 1); buffer_keystring ((char *)&ch, 1); } } static void send_key_sequence (unsigned int n, unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4) { unsigned char buf[4]; if (n > 4) exit_error ("n>4 in send_key_sequence", 0); buf[0] = c1; buf[1] = c2; buf[2] = c3; buf[3] = c4; buffer_keystring((char *)buf, n); } /* Getting defaults from INI file */ static COLORREF msw_get_color(char *s, char *dflt) { if (s[0] >= '0' && s[0] <= '9') { long r, g, b; char *sptr, *endptr; sptr = s; r = strtol(sptr, &endptr, 0); while ((*endptr == ' ') || (*endptr == '\t')) endptr++; /* skipping whitespace */ if ((sptr == endptr) || (*endptr++ != ',')) return msw_get_color(dflt, dflt); sptr = endptr; g = strtol(sptr, &endptr, 0); while ((*endptr == ' ') || (*endptr == '\t')) endptr++; /* skipping whitespace */ if ((sptr == endptr) || (*endptr++ != ',')) return msw_get_color(dflt, dflt); sptr = endptr; b = strtol(sptr, &endptr, 0); while ((*endptr == ' ') || (*endptr == '\t')) endptr++; /* skipping whitespace */ if ((sptr == endptr) || (*endptr++ != 0)) return msw_get_color(dflt, dflt); #if HAS_PALETTE_CODE return PALETTERGB((BYTE)r, (BYTE)g, (BYTE)b); #else return RGB((BYTE)r, (BYTE)g, (BYTE)b); #endif } else { char buf[50]; GetProfileString(szJedSection, s, dflt, buf, sizeof(buf)); if (buf[0] >='0' && buf[0] <= '9') return msw_get_color(buf, dflt); else return msw_get_color(dflt, dflt); } } static void msw_get_default(Msw_Ini_Type *t) { char s[MAX_STRING_SIZE]; GetProfileString(szJedSection, t->name, t->dflt, s, sizeof(s)); switch (t->type) { case MSW_STRING_TYPE: strncpy((char *)t->buf, s, MAX_STRING_SIZE); ((char *)t->buf)[MAX_STRING_SIZE-1] = 0; break; case MSW_INT_TYPE: *(int *)t->buf = atoi(s); break; case MSW_COLOR_TYPE: *(COLORREF *)t->buf = msw_get_color(s, t->dflt); break; } } static void msw_get_defaults(void) { int i = 0; char buf[128]; /* Check for standard color names in INI file. * Add they if cannot find. */ while (Msw_Std_Color[i].name != NULL) { if (!GetProfileString(szJedSection, Msw_Std_Color[i].name, "", buf, sizeof(buf))) msw_define_color(Msw_Std_Color[i].name, &Msw_Std_Color[i].r, &Msw_Std_Color[i].g, &Msw_Std_Color[i].b); i++; } i = 0; while (Msw_Ini_List[i].name != NULL) msw_get_default(&Msw_Ini_List[i++]); } static void get_dc(void) { if (!This_Window.ndc) { This_Window.hdc = GetDC(This_Window.w); #if HAS_PALETTE_CODE SelectPalette (This_Window.hdc, The_Hpalette, FALSE); #endif } This_Window.ndc++; } static void release_dc(void) { assert(This_Window.ndc); if (This_Window.ndc == 1) ReleaseDC(This_Window.w, This_Window.hdc); This_Window.ndc--; } void process_message(void) { MSG msg; if ( #ifdef _MSC_VER GetMessage(&msg, NULL, 0, 0) #else PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) #endif ) { TranslateMessage(&msg); DispatchMessage(&msg); } } static void init_application(void) { WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = JEDWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_IBEAM); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "wjed"; RegisterClass(&wc); } static int select_font(char *fontname, int fontheight, int fontbold) { TEXTMETRIC tm; HFONT font; int height, weight; get_dc(); SetMapMode(This_Window.hdc, MM_TEXT); if (fontbold < 0) weight = FW_DONTCARE; else weight = fontbold > 0 ? FW_BOLD : FW_NORMAL; height = -MulDiv(fontheight, GetDeviceCaps(This_Window.hdc, LOGPIXELSY), 72); font = CreateFont(height, 0, 0, 0, weight, 0, 0, 0, JedCharSet, 0, 0, 0, FIXED_PITCH, fontname); if (font == NULL) { font == CreateFont(height, 0, 0, 0, weight, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, FIXED_PITCH, fontname); } if (font == NULL) { /* This should never happen as we've told CreateFont to use the default */ /* character set if the requested one isn't available. */ jed_verror ("Unable to create instance of '%s' font", fontname); release_dc (); return -1; } if(This_Window.font != NULL) DeleteObject(This_Window.font); This_Window.font = font; This_Window.font_bold = fontbold; This_Window.font_height = fontheight; strncpy(This_Window.font_name, fontname, MAX_STRING_SIZE-1); This_Window.font_name[MAX_STRING_SIZE-1] = '\0'; /* retrieve font metrics (width and base) */ SelectObject(This_Window.hdc, This_Window.font); GetTextMetrics(This_Window.hdc, &tm); This_Window.font_width = tm.tmAveCharWidth; This_Window.font_height = tm.tmHeight; release_dc(); return 0; } static void init_instance (void) { int i; TEXTMETRIC tm; This_Window.hdc = NULL; This_Window.ndc = 0; for (i = 0; i < MAX_MENU_ID; i++) Menu_Callbacks[i] = NULL; InitPopup_Callback = NULL; msw_get_defaults(); /* Apparantly this is wrong */ /* if (This_Window.font_bold < 0) */ /* font_weight = FW_DONTCARE; */ /* else */ /* font_weight = (This_Window.font_bold > 0) ? FW_BOLD : FW_NORMAL; */ /* This_Window.font = CreateFont(-This_Window.font_height, 0, 0, 0, */ /* font_weight, */ /* 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, FIXED_PITCH, */ /* This_Window.font_name); */ #if !HAS_PALETTE_CODE for (i = 0; i < JMAX_COLORS; i++) JColors[i].hbrBG = CreateSolidBrush(JColors[i].bg); #endif msw_normal_video(); /* creating window */ This_Window.w = CreateWindow("wjed", This_Window.title, WS_OVERLAPPEDWINDOW, This_Window.x, This_Window.y, This_Window.width,This_Window.height, NULL, NULL, hInstance, NULL); get_dc(); #if HAS_PALETTE_CODE if ((RC_PALETTE & GetDeviceCaps (This_Window.hdc, RASTERCAPS)) && (NULL != (The_Lplgpl = malloc (sizeof(*The_Lplgpl) - sizeof(The_Lplgpl->palPalEntry) + 2*JMAX_COLORS * sizeof(PALETTEENTRY))))) { The_Lplgpl->palVersion = 0x300; The_Lplgpl->palNumEntries = JMAX_COLORS*2; for (i = 0; i < JMAX_COLORS; i++) { The_Lplgpl->palPalEntry[i*2].peRed = GetRValue (JColors[i].fg); The_Lplgpl->palPalEntry[i*2].peGreen = GetGValue (JColors[i].fg); The_Lplgpl->palPalEntry[i*2].peBlue = GetBValue (JColors[i].fg); The_Lplgpl->palPalEntry[i*2].peFlags = PC_NOCOLLAPSE; The_Lplgpl->palPalEntry[i*2+1].peRed = GetRValue (JColors[i].bg); The_Lplgpl->palPalEntry[i*2+1].peGreen = GetGValue (JColors[i].bg); The_Lplgpl->palPalEntry[i*2+1].peBlue = GetBValue (JColors[i].bg); The_Lplgpl->palPalEntry[i*2+1].peFlags = PC_NOCOLLAPSE; } The_Hpalette = CreatePalette (The_Lplgpl); if (The_Hpalette) { SelectPalette (This_Window.hdc, The_Hpalette, FALSE); RealizePalette (This_Window.hdc); } } /* ReleaseDC (This_Window.w, This_Window.hdc); */ for (i = 0; i < JMAX_COLORS; i++) JColors[i].hbrBG = CreateSolidBrush(JColors[i].bg); #endif /* HAS_PALETTE_CODE */ /* creating fonts, brushes etc */ (void) select_font (Font_Name, Font_Height, Font_Bold); #ifdef _MSC_VER SetTimer (This_Window.w, 43, 100, NULL); #endif /* function that will be called when jed exits (deletes fonts, brushes etc.) */ atexit(msw_cleanup); /* retrieve font metrics (width and base) */ /* get_dc(); */ SelectObject(This_Window.hdc, This_Window.font); GetTextMetrics(This_Window.hdc, &tm); This_Window.font_width = tm.tmAveCharWidth; This_Window.font_height = tm.tmHeight; release_dc(); ShowWindow(This_Window.w, SW_SHOW); UpdateWindow(This_Window.w); #if !defined(__WIN32__) || !JED_HAS_SUBPROCESSES SetTimer(This_Window.w, 42, 30000, NULL); /* used for updating display time */ #endif JedACP = GetACP(); } static int msw_init_term (void) { if (Batch) return 0; hInstance = _hInstance; hPrevInst = _hPrev; if (!hPrevInst) init_application(); init_instance(); return 0; } static void copy_rect(int x1, int y1, int x2, int y2, int x3, int y3) { int dx, dy; RECT rcSrc; dx = (x3 - x1) * This_Window.font_width; dy = (y3 - y1) * This_Window.font_height; SetRect(&rcSrc, x1 * This_Window.font_width, y1 * This_Window.font_height, x2 * This_Window.font_width, y2 * This_Window.font_height); ScrollWindow(This_Window.w, dx, dy, &rcSrc, NULL); #ifdef __WIN32__ UpdateWindow(This_Window.w); #endif } static void blank_rect(int x1, int y1, int x2, int y2) { char blanks[256]; memset (blanks, ' ', sizeof (blanks)); if (This_Window.cursor_showing) hide_cursor(); get_dc (); SelectObject(This_Window.hdc, This_Window.font); SetTextColor(This_Window.hdc, This_Window.current_color->fg); SetBkColor(This_Window.hdc, This_Window.current_color->bg); while (y1 < y2) { int n = x2 - x1; int xx = x1; while (n > 0) { int dn; if (n > (int) sizeof (blanks)) dn = sizeof (blanks); else dn = n; (void) TextOut(This_Window.hdc, xx * This_Window.font_width, y1 * This_Window.font_height, blanks, dn); n -= dn; xx += dn; } y1++; } release_dc (); #if 0 RECT rc; SetRect(&rc, x1 * This_Window.font_width, y1 * This_Window.font_height, x2 * This_Window.font_width, y2 * This_Window.font_height); get_dc(); FillRect(This_Window.hdc, &rc, CURRENT_BG_COLOR); release_dc(); #endif } static void msw_reverse_video(int color) { if ((color < 0) || (color >= JMAX_COLORS)) return; This_Window.current_color = &JColors[color]; } static int smg_read_at(int row, int col, SLsmg_Char_Type *s, unsigned int n) { int saverow, savecol; unsigned int rc; saverow = SLsmg_get_row(); savecol = SLsmg_get_column(); SLsmg_gotorc(row, col); rc = SLsmg_read_raw (s, n); SLsmg_gotorc(saverow, savecol); return rc; } static void _tt_writeW(WCHAR *s, int n, int color) { if (color < 0 || color > JMAX_COLORS) color = 0; get_dc(); SelectObject(This_Window.hdc, This_Window.font); SetTextColor(This_Window.hdc, JColors[color].fg); SetBkColor(This_Window.hdc, JColors[color].bg); TextOutW(This_Window.hdc, This_Window.cursor_col * This_Window.font_width, This_Window.cursor_row * This_Window.font_height, s, n); This_Window.cursor_col += n; if (This_Window.cursor_col >= MSW_Screen_Cols) This_Window.cursor_col = MSW_Screen_Cols - 1; release_dc(); } # define LEAD_OFFSET (0xD800 - (0x10000 >> 10)) static int decode_utf32 (unsigned int u, WCHAR *buf) { if (u < 0xFFFF) { *buf = u; return 1; } else { *(buf) = LEAD_OFFSET + (u >> 10); *(buf+1) = 0xDC00 + (u & 0x3FF); return 2; } } /* SLsmg_Char_Type decode/compare: the char internals changed for SLang2 */ #if SLANG_VERSION >= 20000 static int decode_smgchar(SLsmg_Char_Type *s, WCHAR *buf) { if (s->nchars > 0) return decode_utf32(s->wchars[0], buf); *buf = (WCHAR)' '; return 1; } # define SLSMGCHAR_EQUAL(o, n) \ ( ((o)->nchars == (n)->nchars) \ && ((o)->color == (n)->color) \ && (0 == memcmp((o)->wchars, (n)->wchars, (n)->nchars * sizeof(SLwchar_Type)))) # define SLSMGCHAR_SET_CHAR(sc, _char) do { (sc).nchars = 1; (sc).wchars[0] = (_char); } while (0) # define SLSMGCHAR_SET_COLOR(sc, _color) (sc).color = (_color) #else static int decode_smgchar(SLsmg_Char_Type *s, WCHAR *buf) { *buf = SLSMG_EXTRACT_CHAR(*s); return 1; } # define SLSMGCHAR_EQUAL(o, n) ((o) == (n)) # define SLSMGCHAR_SET_CHAR(sc, _char) (sc) = (sc) & 0xFF00 + (_char) # define SLSMGCHAR_SET_COLOR(sc, _color) (sc) = ((sc) & 0xFF) + ((_color)<<8) /* define this to allow using the same code for slang 1 */ # define SLSMG_COLOR_MASK 0xFF #endif /* SLANG_VERSION >= 20000 */ static void msw_write_smgchars(SLsmg_Char_Type *s, SLsmg_Char_Type *smax) { WCHAR buf[512]; WCHAR *b, *bmax; int oldcolor, color; b = buf; bmax = b + sizeof (buf)/sizeof(buf[0]); hide_cursor(); oldcolor = (SLSMG_EXTRACT_COLOR(*s) & SLSMG_COLOR_MASK); color = 0; get_dc(); for (; s < smax; s++) { color = (SLSMG_EXTRACT_COLOR(*s) & SLSMG_COLOR_MASK); if (oldcolor != color || b >= bmax-1) /* always leave room for 1 more 1 char (for surrogates) */ { _tt_writeW(buf, b - buf, oldcolor); b = buf; msw_reverse_video(color); oldcolor = color; } b += decode_smgchar(s, b); } if (b != buf) _tt_writeW(buf, b - buf, color); release_dc(); } static void msw_write_smgchar(SLsmg_Char_Type *s) { WCHAR buf[2]; int l; get_dc(); l = decode_smgchar(s, buf); _tt_writeW (buf, l, SLSMG_EXTRACT_COLOR(*s) & SLSMG_COLOR_MASK); release_dc(); } static void hide_cursor(void) { SLsmg_Char_Type sc; int col = This_Window.vis_curs_col, row = This_Window.vis_curs_row; int savecur; if (This_Window.cursor_showing == 0) return; This_Window.cursor_showing = 0; if (smg_read_at(row, col, &sc, 1) == 0) { SLSMGCHAR_SET_CHAR(sc, ' '); SLSMGCHAR_SET_COLOR(sc, JNORMAL_COLOR); } savecur = This_Window.cursor_col; msw_write_smgchar(&sc); This_Window.cursor_col = savecur; } static void show_cursor(void) { SLsmg_Char_Type sc; int color; if (This_Window.cursor_showing) hide_cursor(); This_Window.cursor_showing = 1; This_Window.vis_curs_row = This_Window.cursor_row; This_Window.vis_curs_col = This_Window.cursor_col; if (CBuf && CBuf->flags & OVERWRITE_MODE) color = JCURSOROVR_COLOR; else color = JCURSOR_COLOR; if (This_Window.focus) { int savecur; if (smg_read_at(This_Window.cursor_row, This_Window.cursor_col, &sc, 1) == 0) SLSMGCHAR_SET_CHAR(sc, ' '); SLSMGCHAR_SET_COLOR(sc, color); savecur = This_Window.cursor_col; msw_write_smgchar(&sc); This_Window.cursor_col = savecur; } else { RECT rc; rc.left = This_Window.cursor_col * This_Window.font_width; rc.top = This_Window.cursor_row * This_Window.font_height; rc.right = rc.left + This_Window.font_width; rc.bottom = rc.top + This_Window.font_height; get_dc(); FrameRect(This_Window.hdc, &rc, JColors[color].hbrBG); release_dc(); } } void sys_suspend(void) { ShowWindow(This_Window.w, SW_MINIMIZE); } void flush_output (void) { fflush (stdout); } /* Hooks */ static void msw_update_open (void) { hide_cursor (); Performing_Update = 1; } static void msw_update_close (void) { Performing_Update = 0; if (JWindow->trashed) return; show_cursor (); } static int msw_init_slang (void) { if ((-1 == SLadd_intrin_fun_table(Jed_WinGUI_Table, "WINGUI")) || (-1 == SLdefine_for_ifdef ("MOUSE"))) return -1; return 0; } static void msw_suspend (void) { WINDOWPLACEMENT wndpl; GetWindowPlacement(This_Window.w, &wndpl); if (wndpl.showCmd == SW_MINIMIZE) ShowWindow(This_Window.w, SW_NORMAL); else ShowWindow(This_Window.w, SW_MINIMIZE); } static void msw_define_xkeys (SLKeyMap_List_Type *map) { #if 0 /* This is set by doskeys.c */ SLkm_define_key ("^[Ow", (FVOID_STAR) bob, map); SLkm_define_key ("^[Oq", (FVOID_STAR) eob, map); #endif SLkm_define_key ("\xE0\xE0", (FVOID_STAR) ins_char_cmd, map); } /* This routine is called from S-Lang inner interpreter. It serves as a poor mans version of an interrupt 9 handler */ static void msw_check_kbd(void) { MSG msg; if (Batch) return; while (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) process_message(); } /* Terminal functions */ static void msw_goto_rc(int r, int c) { get_dc(); if (This_Window.cursor_showing) hide_cursor(); r += This_Window.scroll_r1; if (r >= MSW_Screen_Rows) r = MSW_Screen_Rows - 1; if (c >= MSW_Screen_Cols) c = MSW_Screen_Cols - 1; This_Window.cursor_row = r; This_Window.cursor_col = c; if (!Performing_Update) show_cursor(); release_dc(); } static void msw_del_eol(void) { blank_rect(This_Window.cursor_col, This_Window.cursor_row, MSW_Screen_Cols, This_Window.cursor_row + 1); } static void msw_delete_nlines(int n) { int r1, r2; r1 = This_Window.cursor_row; r2 = This_Window.scroll_r2; if (r1 <= r2 - n) copy_rect(0, r1 + n, MSW_Screen_Cols, r2 + 1, 0, r1); r2++; blank_rect(0, r2 - n, MSW_Screen_Cols, r2); } #if 0 /* UNUSED */ static void msw_delete_char(void) { copy_rect(This_Window.cursor_col + 1, This_Window.cursor_row, MSW_Screen_Cols, This_Window.cursor_row + 1, This_Window.cursor_col, This_Window.cursor_row); } static void msw_erase_line(void) { blank_rect(0, This_Window.cursor_row, MSW_Screen_Cols, This_Window.cursor_row + 1); } static void msw_begin_insert(void) { hide_cursor(); copy_rect(This_Window.cursor_col, This_Window.cursor_row, MSW_Screen_Cols - 1, This_Window.cursor_row + 1, This_Window.cursor_col + 1, This_Window.cursor_row); } static void msw_end_insert(void) { } /* This function is called assuming that cursor is in correct position */ static void msw_putchar(char ch) { if (ch == '\b') { ch = ' '; if (This_Window.cursor_col == 0) return; This_Window.cursor_col--; } get_dc(); if (Rev_Vid_Flag != JNORMAL_COLOR) msw_normal_video(); tt_write(&ch, 1); show_cursor (); release_dc(); } #endif /* UNUSED */ static void msw_normal_video(void) { msw_reverse_video (JNORMAL_COLOR); } static void msw_cls(void) { RECT rc; get_dc(); GetClientRect(This_Window.w, &rc); FillRect(This_Window.hdc, &rc, CURRENT_BG_COLOR); release_dc(); /* Unfortunately the background color produced by FillRect is slightly different * from the desired background. So patch it up with blank_rect. */ blank_rect (0, 0, MSW_Screen_Cols, MSW_Screen_Rows); } static void msw_beep(void) { if (MSW_Ignore_Beep & 0x1) MessageBeep(0); if (MSW_Ignore_Beep & 0x2) { RECT rc; get_dc(); GetClientRect(This_Window.w, &rc); InvertRect(This_Window.hdc, &rc); release_dc(); InvalidateRect(This_Window.w, NULL, TRUE); #ifdef __WIN32__ UpdateWindow(This_Window.w); #endif } } static void msw_reverse_index(int n) { int r1, r2; r1 = This_Window.scroll_r1; r2 = This_Window.scroll_r2; if (r2 >= r1 + n) copy_rect(0, r1, MSW_Screen_Cols, r2 - n + 1, 0, r1 + n); blank_rect(0, r1, MSW_Screen_Cols, r1 + n); } static void msw_write_string (char *s) { get_dc(); /* tt_write(s, strlen(s)); */ if (!Performing_Update) show_cursor (); release_dc(); } static void msw_smart_puts(SLsmg_Char_Type *neww, SLsmg_Char_Type *oldd, int len, int row) { int col; col = 0; while ((col < len) && SLSMGCHAR_EQUAL(&neww[col], &oldd[col])) col++; if (col < len) { msw_goto_rc (row, col); msw_write_smgchars(&neww[col], &neww[len]); } } static void msw_set_scroll_region(int r1, int r2) { This_Window.scroll_r1 = r1; This_Window.scroll_r2 = r2; } static void msw_reset_scroll_region (void) { msw_set_scroll_region (0, MSW_Screen_Cols - 1); } static int msw_reset_video (void) { msw_reset_scroll_region (); msw_goto_rc (0, 0); msw_normal_video (); return 0; } static int msw_init_video (void) { msw_reset_video (); if ((MSW_Screen_Rows == 0) || (MSW_Screen_Cols == 0)) { MSW_Screen_Cols = 80; MSW_Screen_Rows = 24; } return 0; } static int msw_flush_output (void) { return 0; } static char *convert_color (char *c, char *buf) { unsigned long ul; if ((*c != '#') || (7 != strlen (c))) /* e.g., #RRGGBB */ return c; if (1 != sscanf (c+1, "%lX", &ul)) return c; if (ul > 0xFFFFFFUL) return c; sprintf (buf, "%ld,%ld,%ld", (ul >> 16)&0xFF, (ul >> 8)&0xFF, ul & 0xFF); return buf; } static JX_SETXXX_RETURN_TYPE msw_set_color (int i, char *what, char *fg, char *bg) { int r, g, b; char buf[64]; char fg_buf[64]; char bg_buf[64]; HBRUSH bgbr; if ((i < 0) || (i > JMAX_COLORS)) return JX_SETXXX_RETURN_VAL; (void) what; fg = convert_color (fg, fg_buf); bg = convert_color (bg, bg_buf); r = GetRValue(JColors[i].fg); g = GetGValue(JColors[i].fg); b = GetBValue(JColors[i].fg); sprintf(buf, "%d,%d,%d", r, g, b); JColors[i].fg = msw_get_color(fg, buf); r = GetRValue(JColors[i].bg); g = GetGValue(JColors[i].bg); b = GetBValue(JColors[i].bg); sprintf(buf, "%d,%d,%d", r, g, b); JColors[i].bg = msw_get_color(bg, buf); #if HAS_PALETTE_CODE if (The_Hpalette) { The_Lplgpl->palPalEntry[i*2].peRed = GetRValue (JColors[i].fg); The_Lplgpl->palPalEntry[i*2].peGreen = GetGValue (JColors[i].fg); The_Lplgpl->palPalEntry[i*2].peBlue = GetBValue (JColors[i].fg); The_Lplgpl->palPalEntry[i*2].peFlags = PC_NOCOLLAPSE; The_Lplgpl->palPalEntry[i*2+1].peRed = GetRValue (JColors[i].bg); The_Lplgpl->palPalEntry[i*2+1].peGreen = GetGValue (JColors[i].bg); The_Lplgpl->palPalEntry[i*2+1].peBlue = GetBValue (JColors[i].bg); The_Lplgpl->palPalEntry[i*2+1].peFlags = PC_NOCOLLAPSE; SetPaletteEntries (The_Hpalette, i*2, 2, The_Lplgpl->palPalEntry+i*2); get_dc(); SelectPalette (This_Window.hdc, The_Hpalette, FALSE); RealizePalette (This_Window.hdc); release_dc(); } #endif bgbr = CreateSolidBrush(JColors[i].bg); if (bgbr != 0) { DeleteObject(JColors[i].hbrBG); JColors[i].hbrBG = bgbr; } #if SLANG_VERSION >= 10306 SLsmg_touch_screen (); #endif return JX_SETXXX_RETURN_VAL; /* InvalidateRect(This_Window.w, NULL, FALSE); */ } static void cover_exposed_area (int x, int y, int width, int height) { SLsmg_Char_Type *s; int row, save_row, save_col, max_col, max_row, col; int width_chars, len; Performing_Update++; hide_cursor (); save_row = This_Window.cursor_row; save_col = This_Window.cursor_col; col = x / This_Window.font_width; row = y / This_Window.font_height; width_chars = 2 + width / This_Window.font_width; max_col = col + width_chars; max_row = 2 + row + height / This_Window.font_height; if (max_col > MSW_Screen_Cols) max_col = MSW_Screen_Cols; if (max_row > MSW_Screen_Rows) max_row = MSW_Screen_Rows; if (NULL == (s = (SLsmg_Char_Type *)SLmalloc(width_chars*sizeof(*s)))) goto done; while (row < max_row) { msw_goto_rc (row, col); len = smg_read_at(row, col, s, width_chars); msw_write_smgchars(s, s + len); row++; } SLfree((char *)s); msw_goto_rc (save_row, save_col); done: Performing_Update--; show_cursor (); } static void push_mouse_event(int button, int x, int y, int state, int type) { unsigned int s = 0; int col, row; static int last_button; static JMouse_Type jm; #if JED_HAS_MULTICLICK static long last_press_time; static unsigned int clicks = 0; static long MultiClick_Time = -1; #endif int id; col = 1 + x / This_Window.font_width; row = 1 + y / This_Window.font_height; if ((type == JMOUSE_DRAG) && (col == jm.x) && (row == jm.y)) return; if (button == 0) button = last_button; else last_button = button; #if JED_HAS_MULTICLICK if (type == JMOUSE_DOWN) { long the_time = GetTickCount(); if (MultiClick_Time == -1) MultiClick_Time = GetDoubleClickTime(); if ((last_button == button) && (the_time - last_press_time < MultiClick_Time)) { clicks++; if (clicks == 2) type = JMOUSE_DOUBLE_CLICK; else type = JMOUSE_TRIPLE_CLICK; } else { clicks = 1; last_button = button; } last_press_time = the_time; } else if ((clicks > 1) && (last_button == button)) { /* Last was a multi-click. Ignore this event. */ type = JMOUSE_IGNORE_EVENT; } #endif jm.button = button; if ((type == JMOUSE_UP) && (0 == (jm.state & jm.button))) { /* Make sure this button was down. */ return; } if (state & MK_LBUTTON) s |= JMOUSE_BUTTON_1; if (state & MK_MBUTTON) s |= JMOUSE_BUTTON_2; if (state & MK_RBUTTON) s |= JMOUSE_BUTTON_3; if (state & MK_CONTROL) s |= JMOUSE_CTRL; if (state & MK_SHIFT) s |= JMOUSE_SHIFT; jm.state = s; jm.x = col; jm.y = row; jm.type = type; if (-1 == (id = jed_mouse_add_event (&jm))) { msg_error ("Failed!"); return; } send_key_sequence(3, 033, 0, id, 0); } static void push_wm_mouse_event (int button, int x, int y, int state, int type) { switch (button) { case WM_LBUTTONUP: case WM_LBUTTONDOWN: if (!(GetKeyState(VK_MENU) & 0x8000)) { button = JMOUSE_BUTTON_1; break; } /* drop */ case WM_MBUTTONUP: case WM_MBUTTONDOWN: button = JMOUSE_BUTTON_2; break; case WM_RBUTTONUP: case WM_RBUTTONDOWN: button = JMOUSE_BUTTON_3; break; default: return; } push_mouse_event (button, x, y, state, type); } static void msw_define_color(char *color_name, int *pr, int *pg, int *pb) { char buf[30]; sprintf(buf, "%d,%d,%d", *pr, *pg, *pb); WriteProfileString(szJedSection, color_name, buf); } static void msw_select_font (char *fontname, int *height, int *bold) { if (0 == select_font (fontname, *height, *bold)) { jed_init_display (); jed_redraw_screen (1); /* update font data, As I need it if the user changes Language */ strcpy(Font_Name, fontname); Font_Height = *height; Font_Bold = *bold; return; } jed_verror ("Unable to allocate font %s", fontname); } static void set_window_name (char *s) { if (Batch) return; strcpy(This_Window.title, s); SetWindowText(This_Window.w, s); } static void msw_cleanup(void) { int i; char buf[10]; RECT rc; GetWindowRect(This_Window.w, &rc); sprintf(buf, "%d", (int) rc.left); WriteProfileString(szJedSection, "X", buf); sprintf(buf, "%d", (int) rc.top); WriteProfileString(szJedSection, "Y", buf); sprintf(buf, "%d", (int) (rc.right - rc.left)); WriteProfileString(szJedSection, "Width", buf); sprintf(buf, "%d", (int) (rc.bottom - rc.top)); WriteProfileString(szJedSection, "Height", buf); KillTimer(This_Window.w, 42); #ifdef _MSC_VER KillTimer (This_Window.w, 43); #endif if (This_Window.w) DestroyWindow(This_Window.w); DeleteObject(This_Window.font); for(i = 0; i < JMAX_COLORS; i++) if (JColors[i].hbrBG) DeleteObject(JColors[i].hbrBG); } #if !defined(__WIN32__) || !JED_HAS_SUBPROCESSES int sys_input_pending(int *tsecs, int unused) { DWORD t = GetTickCount() + *tsecs * 100L; (void) unused; while ((!Input_Buffer_Len) && (GetTickCount() < t)) process_message(); return Input_Buffer_Len != 0; } unsigned char sys_getkey(void) { int n; while (!SLKeyBoard_Quit && !Input_Buffer_Len) process_message (); if (SLKeyBoard_Quit) { SLKeyBoard_Quit = 0; flush_input (); return Jed_Abort_Char; } n = my_getkey(); SLKeyBoard_Quit = 0; return n; } #else int sys_input_pending(int *tsecs, int all) { DWORD ret = 0; int i, n; if ((all >= 0) && (Input_Buffer_Len || Batch)) return (Input_Buffer_Len); if (all < 0) { /* Note: Input_Events[0] is only used by console jed. */ ret = WaitForMultipleObjects(Num_Subprocesses, Input_Events+1, FALSE, *tsecs * 100); } else { DWORD t; long rtime = *tsecs * 100L; msw_check_kbd (); while ((rtime > 0) && !Input_Buffer_Len) { t = GetTickCount(); ret = MsgWaitForMultipleObjects(Num_Subprocesses, Input_Events+1, FALSE, rtime, QS_ALLINPUT); if ((DWORD)(WAIT_OBJECT_0 + Num_Subprocesses) != ret) break; msw_check_kbd (); rtime -= GetTickCount() - t; } if ((rtime < 0) || Input_Buffer_Len) return Input_Buffer_Len; } if (WAIT_TIMEOUT == ret) return 0; n = 0; i = 1; /* First input event is not used by wjed. Start at 1. */ while (i <= Num_Subprocesses) { /* Check if current subprocess has input */ if (WAIT_TIMEOUT != WaitForSingleObject(Input_Events[i], 0)) { read_process_input (i); n++; } i++; } if (all < 0) return n; else return 0; } unsigned char sys_getkey(void) { int n = 450; /* sleep for 45 second and try again */ while (!SLKeyBoard_Quit && !sys_input_pending(&n, Num_Subprocesses)) { /* update status line incase user is displaying time */ if (SLKeyBoard_Quit) break; JWindow->trashed = 1; update((Line *) NULL, 0, 1, 0); } if (SLKeyBoard_Quit) { SLKeyBoard_Quit = 0; flush_input (); return Jed_Abort_Char; } return my_getkey(); } #endif static int Ignore_Wchar_Message; static unsigned char f_keys[4][12] = { { 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 133, 134 }, { 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 135, 136 }, { 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 137, 138 }, { 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 139, 140 } }; static unsigned char small_keypad_keys[4][13] = { { 'G', 'H', 'I', 0, 'K', 0, 'M', 0, 'O', 'P', 'Q', 'R', 'S' }, /* normal */ { '0', '1', '2', 0, '3', 0, '4', 0, '5', '6', '7', '8', '9' }, /* shift */ { 'w', 141, 132, 0, 's', 0, 't', 0, 'u', 145, 'v', 146, 147 }, /* ctrl */ { 151, 152, 153, 0, 155, 0, 157, 0, 159, 160, 161, 162, 163 } /* alt */ }; static unsigned char num_keypad_keys[4][13] = { { 'w', 'x', 'y', 0, 't', 'u', 'v', 0, 'q', 'r', 's', 'p', 'n' }, { '0', '1', '2', 0, '3', 0 , '4', 0, '5', '6', '7', '8', '9' }, { 'w', 141, 132, 0, 's', 143, 't', 0, 'u', 145, 'v', 146, 147 }, { 'w', 'x', 'y', 0, 't', 'u', 'v', 0, 'q', 'r', 's', 'p', 'n' } }; static LRESULT CALLBACK process_key_down (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { unsigned int key_state = 0; unsigned int scan; unsigned char prefix, c1; int i, state; if (GetKeyState(VK_CONTROL) & 0x8000) key_state |= KEY_CONTROL; if (GetKeyState(VK_SHIFT) & 0x8000) key_state |= KEY_SHIFT; if (GetKeyState(VK_MENU) & 0x8000) key_state |= KEY_ALT; Ignore_Wchar_Message = 0; scan = (unsigned int) ((lParam >> 16) & 0x1FF); switch (scan) { default: return DefWindowProc(hWnd, msg, wParam, lParam); case 0x00E: /* backspace */ /* Ctrl-BS --> ALT-@ * Shift-BS --> ALT-? * BS --> ^? */ if ((key_state & KEY_ALT) == 0) { if ((key_state & KEY_CONTROL) != 0) send_key_sequence(2, PC_Alt_Char, '@', 0, 0); else if ((key_state & KEY_SHIFT) != 0) send_key_sequence(2, PC_Alt_Char, '?', 0, 0); else send_key_sequence(1, 127, 0, 0, 0); } Ignore_Wchar_Message = 1; return 0; case 0x039: /* space */ if (key_state & KEY_CONTROL) { Ignore_Wchar_Message = 1; buffer_keystring ("\000\003", 2); } return 0; case 0x003: /* 2 key */ if (((key_state & KEY_ALT) == 0) && (key_state & KEY_CONTROL)) { Ignore_Wchar_Message = 1; buffer_keystring ("\000\003", 2); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); case 0x00C: /* -/_ key */ if (((key_state & KEY_ALT) == 0) && (key_state & KEY_CONTROL)) { Ignore_Wchar_Message = 1; send_key_sequence(1, 31, 0, 0, 0); /* ^_ */ return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); /* PF1 and PF2 codes */ /* case 0x0045: */ case 0x0145: if (NumLock_Is_Gold) { #if 0 /* does not work on xp */ BYTE keyState[256]; /* toggle the caps-lock state */ GetKeyboardState(keyState); keyState[VK_NUMLOCK] = 0;/*keyState[VK_NUMLOCK]^1;*/ SetKeyboardState(keyState); #endif buffer_keystring ("\033OP", 3); Ignore_Wchar_Message = 1 ; return 0 ; } return DefWindowProc(hWnd, msg, wParam, lParam); case 0x0135: c1 = 'Q'; break ; case 0xE02F: c1 = 'Q'; break; /* KEYPAD SLASH */ case 0x037: /* KEYPAD STAR */ c1 = 'R'; break; case 0x04A: /* KEYPAD MINUS */ c1 = 'S'; break; case 0x04E: /* KEYPAD PLUS */ c1 = 'm'; break; case 0x047: /* KEYPAD HOME */ case 0x048: /* KEYPAD UP */ case 0x049: /* KEYPAD PGUP */ case 0x04B: /* KEYPAD LEFT */ case 0x04C: /* KEYPAD 5 */ case 0x04D: /* KEYPAD RIGHT */ case 0x04F: /* KEYPAD END */ case 0x050: /* KEYPAD DOWN */ case 0x051: /* KEYPAD PGDN */ case 0x053: /* KEYPAD DEL */ case 0x052: /* KEYPAD INSERT */ if (!NumLock_Is_Gold && (GetKeyState(VK_NUMLOCK) & 0x0001)) return DefWindowProc(hWnd, msg, wParam, lParam); state = 0; if (key_state & KEY_SHIFT) state = 1; if (key_state & KEY_CONTROL) state = 2; if (key_state & KEY_ALT) state = 3; if (key_state & (KEY_CONTROL | KEY_ALT)) { Ignore_Wchar_Message = 1; send_key_sequence(2, 0, num_keypad_keys[state][scan - 0x47], 0, 0); return 0; } else c1 = num_keypad_keys[state][scan - 0x47]; break; case 0x11C: /* KEYPAD ENTER */ if (key_state & KEY_ALT) { send_key_sequence(2, 0, 166, 0, 0); Ignore_Wchar_Message = 1; return 0; } else { c1 = 'M'; break; } case 0x147: /* home */ case 0x148: /* UP */ case 0x149: /* PGUP */ case 0x14B: /* LEFT */ case 0x14D: /* RIGHT */ case 0x14F: /* END */ case 0x150: /* DOWN */ case 0x151: /* PGDN */ case 0x153: /* DEL */ case 0x152: /* INSERT */ prefix = 0xE0; state = 0; if (key_state & KEY_SHIFT) state = 1; if (key_state & KEY_CONTROL) state = 2; if (key_state & KEY_ALT) { prefix = 0; state = 3; } send_key_sequence(2, prefix, small_keypad_keys[state][scan - 0x147], 0, 0); Ignore_Wchar_Message = 1; return 0; case 0x3b: /* F1 */ case 0x3c: case 0x3d: case 0x3e: case 0x3f: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x57: case 0x58: /* F12 */ i = scan - 0x3b; if (i > 9) i -= 0x12; state = 0; if (key_state & KEY_SHIFT) state = 1; if (key_state & KEY_CONTROL) state = 2; if (key_state & KEY_ALT) { if (i == 3) /* Alt-F4 */ return DefWindowProc(hWnd, msg, wParam, lParam); else state = 3; } send_key_sequence(2, PC_Fn_Char, f_keys[state][i], 0, 0); Ignore_Wchar_Message = 1; return 0; } send_key_sequence(3, 033, 'O', c1, 0); Ignore_Wchar_Message = 1; return 0; } static int load_dropped_files(HDROP hDrop, HWND hwnd) { char szFilename[JED_MAX_PATH_LEN]; int iNumFiles; (void) hwnd; iNumFiles = DragQueryFile (hDrop, 0xFFFFFFFF, NULL, JED_MAX_PATH_LEN-1); while(--iNumFiles>=0) { DragQueryFile(hDrop, iNumFiles, szFilename, JED_MAX_PATH_LEN-1); (void) find_file_in_window(szFilename); window_buffer(CBuf); jed_redraw_screen (1); } DragFinish(hDrop); return 0; } LRESULT CALLBACK JEDWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { static int mouse_button_down; PAINTSTRUCT ps; RECT rc; switch (msg) { case WM_INPUTLANGCHANGE: { CHARSETINFO csi; JedCharSet = wParam; TranslateCharsetInfo((DWORD *)wParam, &csi, TCI_SRCCHARSET); JedACP = csi.ciACP; (void) msw_select_font (Font_Name, &Font_Height, &Font_Bold); } return 0; case WM_CREATE: This_Window.w = hWnd; DragAcceptFiles (hWnd, TRUE); mouse_button_down = 0; return 0; case WM_DROPFILES: (void) load_dropped_files ((HANDLE) wParam, hWnd); return 0; case WM_SIZE: if (wParam != SIZE_MINIMIZED) { This_Window.width = LOWORD(lParam); This_Window.height = HIWORD(lParam); jed_init_display (); jed_redraw_screen (1); } break; case WM_PAINT: BeginPaint(This_Window.w, &ps); #if HAS_PALETTE_CODE if (NULL != The_Hpalette) SelectPalette (ps.hdc, The_Hpalette, FALSE); #endif This_Window.hdc = ps.hdc; This_Window.ndc = 1; cover_exposed_area(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top); EndPaint(This_Window.w, &ps); This_Window.hdc = NULL; This_Window.ndc = 0; break; #if HAS_PALETTE_CODE case WM_PALETTECHANGED: if (wParam != This_Window.w && The_Hpalette != NULL) { get_dc(); UpdateColors (This_Window.hdc); release_dc(); } break; case WM_QUERYNEWPALETTE: if (The_Hpalette != NULL) { get_dc(); RealizePalette (This_Window.hdc); release_dc(); } break; #endif case WM_ERASEBKGND: GetClientRect(This_Window.w, &rc); FillRect((HDC)wParam, &rc, CURRENT_BG_COLOR); break; case WM_SYSCHAR: _putkey(PC_Alt_Char); if (PC_Alt_Char != 0) _putkey (wParam); else _putkey((lParam >> 16) & 0x1FF);/* was: _putkey(wParam); */ return MAKELONG(0, 1); case WM_CHAR: if (Ignore_Wchar_Message == 0) { if ((int) wParam == (int) Jed_Abort_Char) { if (Ignore_User_Abort == 0) SLang_set_error(USER_BREAK); SLKeyBoard_Quit = 1; } /* PS 28Apr98: handle shiftTAB same as DOS */ if (wParam == 0x009) { if (GetKeyState(VK_SHIFT)<0) { send_key_sequence(2, 0, 'o' & 31, 0, 0); Ignore_Wchar_Message = 1; break; } } if (!wjed_has_unicode()) _putkey(wParam); else { static char dbcsbuf[3] = ""; WCHAR buf[10]; int i, buflen = 10; int dbcsl; // Here I get ANSI characters, but _putkey() wants UTF-16. if (!dbcsbuf[0] && IsDBCSLeadByte((unsigned char)wParam)) { dbcsbuf[0] = (char)wParam; break; } dbcsl = 1; if (dbcsbuf[0]) { dbcsbuf[1] = (unsigned char) wParam; dbcsl = 2; } else { dbcsbuf[0] = (unsigned char) wParam; } dbcsbuf[2] = 0; buflen = MultiByteToWideChar(JedACP, 0, dbcsbuf, dbcsl, buf, buflen); for (i = 0; i < buflen; i++) _putkey(buf[i]); dbcsbuf[0] = 0; } break; } return DefWindowProc(hWnd, msg, wParam, lParam); case WM_SYSKEYDOWN: case WM_KEYDOWN: return process_key_down (hWnd, msg, wParam, lParam); case WM_KEYUP: Ignore_Wchar_Message = 0; break; case WM_SYSKEYUP: Ignore_Wchar_Message = 0; return DefWindowProc(hWnd, msg, wParam, lParam); case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: if (!mouse_button_down) break; push_wm_mouse_event(msg, LOWORD(lParam), HIWORD(lParam), wParam, JMOUSE_UP); mouse_button_down--; break; case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: mouse_button_down++; push_wm_mouse_event(msg, LOWORD(lParam), HIWORD(lParam), wParam, JMOUSE_DOWN); break; case WM_MOUSEMOVE: if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) push_mouse_event(0, LOWORD(lParam), HIWORD(lParam), wParam, JMOUSE_DRAG); break; case WM_SETFOCUS: case WM_KILLFOCUS: hide_cursor(); This_Window.focus = (msg == WM_SETFOCUS); show_cursor(); break; #if 0 /* This does not quite work when coming back from a shell */ case WM_ACTIVATE: if ((wParam != WA_INACTIVE) && (CBuf != NULL)) check_buffers(); break; #endif case WM_CLOSE: jed_exit_jed(1); break; #if !defined(__WIN32__) || !JED_HAS_SUBPROCESSES case WM_TIMER: if ((wParam == 42) && Display_Time) { JWindow->trashed = 1; update((Line *) NULL, 0, 1, 0); } return 0; #endif #if defined(_MSC_VER) && JED_HAS_SUBPROCESSES case WM_TIMER: /* * just stop the GetMessage call... */ return 0; #endif case WM_COMMAND: if (wParam < MAX_MENU_ID) { int force = 1; if (Menu_Callbacks[wParam]) { if (is_internal(Menu_Callbacks[wParam])) { char buf[512]; SLsnprintf(buf, sizeof (buf), ". \"%s\" call", Menu_Callbacks[wParam]); SLang_load_string (buf); } else if (SLang_execute_function(Menu_Callbacks[wParam]) == 0) msg_error(Menu_Callbacks[wParam]); } update_cmd(&force); } return 0; case WM_INITMENUPOPUP: SLang_push_integer(wParam); if (InitPopup_Callback != NULL) if (SLang_execute_function(InitPopup_Callback) == 0) msg_error(InitPopup_Callback); return 0; default: #if HAS_WHEEL_MOUSE_SUPPORT /* Check for a mouse wheel movement message * and translate it into a fake keystroke. This has now been * tested on Win95,98,NT4,2000 */ if ((Wheel_Mouse.fActive && (msg == Wheel_Mouse.uiMshMsgMouseWheel)) || (msg == WM_MOUSEWHEEL)) { /* Under X, the wheel mouse produces JMOUSE_BUTTON_4 and * JMOUSE_BUTTON_5 events. jed/lib/mouse.sl maps JMOUSE_BUTTON_4 * events to upward movement and JMOUSE_BUTTON_5 to downward * movement in the buffer. */ if ((int) wParam < 0) push_mouse_event (JMOUSE_BUTTON_5, LOWORD(lParam), HIWORD(lParam), wParam, JMOUSE_DOWN); else push_mouse_event (JMOUSE_BUTTON_4, LOWORD(lParam), HIWORD(lParam), wParam, JMOUSE_DOWN); return 0; } #endif return DefWindowProc(hWnd, msg, wParam, lParam); } return 0; } static int pop_hmenu (HMENU *h) { int i; if (-1 == SLang_pop_integer (&i)) return -1; *h = (HMENU) i; return 0; } static int push_hmenu (HMENU h) { return SLang_push_integer ((int) h); } void get_menubar() { HMENU hmenu = GetMenu(This_Window.w); if (!hmenu) { hmenu = CreateMenu(); SetMenu(This_Window.w, hmenu); DrawMenuBar(This_Window.w); } (void) push_hmenu (hmenu); } void destroy_menubar() { int i; HMENU hmenu = GetMenu(This_Window.w); if (hmenu) { SetMenu(This_Window.w, NULL); DestroyMenu(hmenu); } for(i = 0; i < MAX_MENU_ID; i++) Menu_Callbacks[i] = NULL; } void create_popup_menu() { HMENU hmenu = CreatePopupMenu(); (void) push_hmenu (hmenu); } void destroy_menu() { HMENU hmenu; int count, i; int id; if (0 == pop_hmenu (&hmenu)) { count = GetMenuItemCount(hmenu); for(i = 0; i < count; i++) { id = GetMenuItemID(hmenu, i); if (id > 0 && Menu_Callbacks[id] != NULL) { SLfree(Menu_Callbacks[id]); Menu_Callbacks[id] = NULL; } } if (!DestroyMenu(hmenu)) msg_error("Cannot destroy menu"); } } void append_menu_item() { HMENU hmenu; char *name = NULL; char *callback = NULL; int id; if (!SLpop_string(&callback) && !SLang_pop_integer(&id) && !SLpop_string(&name) && !pop_hmenu (&hmenu)) { if ((id < 0) || (id >= MAX_MENU_ID)) msg_error("Id is out of range."); else { if (!AppendMenu(hmenu, MF_STRING, id, name)) msg_error("Cannot append menu item"); else { if (Menu_Callbacks[id] != NULL) { jed_verror ("Id %d is already used.", id); } else { Menu_Callbacks[id] = callback; callback = NULL; } } } } if (name != NULL) SLfree(name); if (callback != NULL) SLfree(callback); } void append_popup_menu() { HMENU hmenu; char *name = NULL; HMENU popup; if (!pop_hmenu(&popup) && !SLpop_string (&name) && !pop_hmenu(&hmenu)) { if (!AppendMenu(hmenu, MF_STRING | MF_POPUP, (UINT)popup, name)) msg_error("Cannot append popup menu"); } if (name != NULL) SLfree(name); } void append_separator() { HMENU hmenu; if (!pop_hmenu (&hmenu)) { if (!AppendMenu(hmenu, MF_STRING | MF_SEPARATOR, 0, 0)) msg_error("Cannot append separator"); } } void insert_menu_item() { HMENU hmenu; int id; char *name = NULL; int idNew; char *callback = NULL; if (!SLpop_string(&callback) && !SLang_pop_integer(&idNew) && !SLpop_string(&name) && !SLang_pop_integer(&id) && !pop_hmenu(&hmenu)) { if ((idNew < 0) || (idNew >= MAX_MENU_ID)) msg_error("Id is out of range"); else { if (!InsertMenu(hmenu, id, MF_STRING | MF_BYCOMMAND, idNew, name)) msg_error("Cannot insert menu item"); else { if (Menu_Callbacks[idNew] != NULL) { jed_verror ("Id %d is already used.", idNew); } else { Menu_Callbacks[idNew] = callback; callback = NULL; } } } } if (name != NULL) SLfree(name); if (callback != NULL) SLfree(callback); } void insert_popup_menu() { HMENU hmenu; int id; char *name = NULL; HMENU popup; if (!pop_hmenu(&popup) && !SLpop_string (&name) && !SLang_pop_integer(&id) && !pop_hmenu(&hmenu)) { if (!InsertMenu(hmenu, id, MF_STRING | MF_POPUP | MF_BYCOMMAND, (UINT)popup, name)) msg_error("Cannot insert popup menu"); } if (name != NULL) SLfree (name); } void insert_separator() { HMENU hmenu; int id; if (!SLang_pop_integer(&id) && !pop_hmenu (&hmenu)) { if (!InsertMenu(hmenu, id, MF_STRING | MF_SEPARATOR | MF_BYCOMMAND, 0, 0)) msg_error("Cannot insert separator"); } } void insert_menu_item_pos() { HMENU hmenu; int pos; char *name = NULL; int idNew; char *callback = NULL; if (!SLpop_string(&callback) && !SLang_pop_integer(&idNew) && !SLpop_string(&name) && !SLang_pop_integer(&pos) && !pop_hmenu(&hmenu)) { if ((idNew < 0) || (idNew >= MAX_MENU_ID)) msg_error("Id is out of range."); else { if (!InsertMenu(hmenu, pos, MF_STRING | MF_BYPOSITION, idNew, name)) msg_error("Cannot insert menu item"); else { if (Menu_Callbacks[idNew] != NULL) { jed_verror ("Id %d is already used.", idNew); } else { Menu_Callbacks[idNew] = callback; callback = NULL; } } } } if (name != NULL) SLfree(name); if (callback != NULL) SLfree(callback); } void insert_popup_menu_pos() { HMENU hmenu; int pos; char *name = NULL; HMENU popup; if (!pop_hmenu(&popup) && !SLpop_string(&name) && !SLang_pop_integer(&pos) && !pop_hmenu(&hmenu)) { if (!InsertMenu(hmenu, pos, MF_STRING | MF_POPUP | MF_BYPOSITION, (UINT)popup, name)) msg_error("Cannot insert popup menu"); } if (name != NULL) SLfree(name); } void insert_separator_pos() { HMENU hmenu; int pos; if (!SLang_pop_integer(&pos) && !pop_hmenu(&hmenu)) { if (!InsertMenu(hmenu, pos, MF_STRING | MF_SEPARATOR | MF_BYPOSITION, 0, 0)) msg_error("Cannot insert separator"); } } void delete_menu_item() { HMENU hmenu; int id; if (!SLang_pop_integer(&id) && !pop_hmenu(&hmenu)) { if ((id < 0) || (id >= MAX_MENU_ID)) { msg_error("Id is out of range."); return; } if (!DeleteMenu(hmenu, id, MF_BYCOMMAND)) msg_error("Cannot delete menu"); else { if (Menu_Callbacks[id]) { SLfree(Menu_Callbacks[id]); Menu_Callbacks[id] = NULL; } } } } void delete_menu_item_pos() { HMENU hmenu, popup; int pos; int id; if (!SLang_pop_integer(&pos) && !pop_hmenu(&hmenu)) { id = GetMenuItemID(hmenu, pos); if ((id > 0) && (Menu_Callbacks[id] != NULL)) { SLfree(Menu_Callbacks[id]); Menu_Callbacks[id] = NULL; } else if (id == -1) { popup = GetSubMenu(hmenu, pos); (void) push_hmenu (popup); destroy_menu(); } if (!DeleteMenu(hmenu, pos, MF_BYPOSITION)) msg_error("Cannot delete menu"); } } void get_menu_state() { HMENU hmenu; int id; UINT mstate; int state; if (!SLang_pop_integer(&id) && !pop_hmenu(&hmenu)) { if (-1 == (int)(mstate = GetMenuState(hmenu, id, MF_BYCOMMAND))) msg_error("Cannot get menu state"); else { state = 0; if (mstate & MF_ENABLED) state = 1; if (mstate & MF_CHECKED) state |= 2; (void)SLang_push_integer(state); } } } void get_menu_state_pos() { HMENU hmenu; int pos; UINT mstate; int state; if (!SLang_pop_integer(&pos) && !pop_hmenu(&hmenu)) { if (-1 == (int)(mstate = GetMenuState(hmenu, pos, MF_BYPOSITION))) msg_error("Cannot get menu state"); else { state = 0; if (mstate & MF_GRAYED) state = 1; if (mstate & MF_CHECKED) state |= 2; (void)SLang_push_integer(state); } } } void get_popup_menu() { HMENU hmenu; int pos; HMENU popup; if (!SLang_pop_integer(&pos) && !pop_hmenu(&hmenu)) { popup = GetSubMenu(hmenu, pos); (void) push_hmenu (popup); } } void check_menu_item() { HMENU hmenu; int id; int flag; if (!SLang_pop_integer(&flag) && !SLang_pop_integer(&id) && !pop_hmenu(&hmenu)) { if (-1 == (int) CheckMenuItem(hmenu, id, MF_BYCOMMAND | (flag)?MF_CHECKED:MF_UNCHECKED)) msg_error("Menu item does not exist"); } } void check_menu_item_pos() { HMENU hmenu; int pos; int flag; if (!SLang_pop_integer(&flag) && !SLang_pop_integer(&pos) && !pop_hmenu(&hmenu)) { if (!CheckMenuItem(hmenu, pos, MF_BYPOSITION | (flag)?MF_CHECKED:MF_UNCHECKED)) msg_error("Menu item does not exist"); } } void enable_menu_item() { HMENU hmenu; int id; int flag; if (!SLang_pop_integer(&flag) && !SLang_pop_integer(&id) && !pop_hmenu(&hmenu)) { if (-1 == EnableMenuItem(hmenu, id, MF_BYCOMMAND | (flag)?MF_ENABLED:MF_GRAYED)) msg_error("Menu item does not exist"); } } void enable_menu_item_pos() { HMENU hmenu; int pos; int flag; if (!SLang_pop_integer(&flag) && !SLang_pop_integer(&pos) && !pop_hmenu(&hmenu)) { if (-1 == EnableMenuItem(hmenu, pos, MF_BYPOSITION | (flag)?MF_ENABLED:MF_DISABLED)) msg_error("Menu item does not exist"); } } void redraw_menubar() { DrawMenuBar(This_Window.w); } void set_init_popup_callback() { char *callback; if (SLpop_string(&callback)) return; if (InitPopup_Callback != NULL) SLfree(InitPopup_Callback); InitPopup_Callback = callback; } void msw_help (void) { char *file = NULL; char *keyword = NULL; int partial_keyword; UINT help_type; DWORD dwData; if (!SLang_pop_integer(&partial_keyword) && !SLpop_string (&keyword) && !SLpop_string(&file)) { help_type = (partial_keyword) ? HELP_PARTIALKEY : HELP_KEY; dwData = (DWORD)(LPSTR) keyword; if (*keyword == '\0') { help_type = HELP_CONTENTS; dwData = 0; } if (!WinHelp(This_Window.w, file, help_type, dwData)) { msg_error("Help file not found."); } } if (keyword != NULL) SLfree(keyword); if (file != NULL) SLfree(file); } static void msw_get_display_size (int *rows, int *cols) { *cols = MSW_Screen_Cols = This_Window.width / This_Window.font_width; *rows = MSW_Screen_Rows = This_Window.height / This_Window.font_height; } static JX_SETXXX_RETURN_TYPE msw_set_mono (int i, char *what , SLtt_Char_Type unused) { (void)i; (void)what; (void)unused; return JX_SETXXX_RETURN_VAL; } int jed_init_w32_support (void) { return w32_init_subprocess_support (1); } #if HAS_WHEEL_MOUSE_SUPPORT /* Initialise mouse wheel handling functionality */ static int init_wheel_mouse (void) { /* Find the mystery mouse window */ Wheel_Mouse.hwnd = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); /* Register messages to determine mousey information */ Wheel_Mouse.uiMshMsgMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL); Wheel_Mouse.uiMshMsg3DSupport = RegisterWindowMessage(MSH_WHEELSUPPORT); Wheel_Mouse.uiMshMsgScrollLines = RegisterWindowMessage(MSH_SCROLL_LINES); /* If we have a wheel enquiry message, ask about the presence of a wheel */ if (Wheel_Mouse.uiMshMsg3DSupport) Wheel_Mouse.fActive = (BOOL)SendMessage(Wheel_Mouse.hwnd, Wheel_Mouse.uiMshMsg3DSupport, 0, 0); else Wheel_Mouse.fActive = FALSE; /* If we have a scroll line enquiry message ask about that */ if (Wheel_Mouse.uiMshMsgScrollLines) Wheel_Mouse.iScrollLines = (int)SendMessage(Wheel_Mouse.hwnd, Wheel_Mouse.uiMshMsgScrollLines, 0, 0); else Wheel_Mouse.iScrollLines = 3; return 0; } #endif /* HAS_WHEEL_MOUSE_SUPPORT */ #if defined(__BORLANDC__) || defined(__WIN32__) || defined(__VC__) extern int main(int, char **); int PASCAL WinMain(HINSTANCE inst, HINSTANCE pinst, LPSTR lpszCmdLine, int nCmdShow) { char **argv; int argc; int count; char *pt; int ret; char *command_line; /* add 8 for "wjed", the separating space, and a terminating '\0' */ if (NULL == (command_line = SLMALLOC (strlen(lpszCmdLine) + 6))) return 0; #ifdef _MSC_VER _hInstance = inst; #else (void) inst; #endif (void) nCmdShow; #if HAS_WHEEL_MOUSE_SUPPORT (void) init_wheel_mouse (); #endif strcpy(command_line, "wjed "); strcat(command_line, lpszCmdLine); _hPrev = pinst; /* Handle quoted filenames containing space characters. It is a pity * that the application has to do this. */ while ( (*command_line != '\0') && (*command_line == ' ')) command_line++; /* start on 1st non-space */ pt = command_line; count = 0; while ( *pt != '\0' ) { count++; /* this is an argument */ #ifdef __WIN32__ /* If the first character of the argument is a double quote, * search for a matching double-quote to end the argument, * otherwise, find the next space */ if (*pt == '"') { pt++; /* Skip the initial quote */ while ((*pt != '\0') && (*pt != '"')) pt++; if (*pt != '\0') /* Skip the end quote */ pt++; } else #endif while ((*pt != '\0') && (*pt != ' ')) pt++; /* advance until a space */ while (*pt == ' ') pt++; /* advance until a non-space */ } argv = (char **) SLMALLOC( (count+3) * sizeof(char *) ); if (argv == NULL ) return 0; /* malloc error */ argc = 0; pt = command_line; while ((argc < count) && (*pt != '\0')) { argv[ argc ] = pt; argc++; #ifdef __WIN32__ /* If the first character of the argument is a double quote, * search for a matching double-quote to end the argument, * otherwise, find the next space */ if (*pt == '"') { pt++; /* Skip the initial quote */ while ((*pt != '\0') && (*pt != '"')) pt++; if (*pt != '\0') /* Skip the end quote */ pt++; } else #endif while ( *pt != '\0' && *pt != ' ' ) pt++; /* advance until a space */ if ( *pt != '\0' ) *(pt++) = '\0'; /* parse argument here */ while ( *pt == ' ') pt++; /* advance until a non-space */ } argv [ argc ] = (char *) NULL; /* NULL terminated list */ ret = main(argc, argv); SLfree(command_line); return ret; } #endif /* __BORLANDC__ || __VC__ */ void (*tt_beep)(void); void (*tt_write_string)(char *); JX_SETXXX_RETURN_TYPE (*tt_set_color)(int, char *, char *, char *); JX_SETXXX_RETURN_TYPE (*tt_set_mono) (int, char *, SLtt_Char_Type); void (*tt_get_screen_size)(int *, int *); int *tt_Ignore_Beep; int *tt_Use_Ansi_Colors; int *tt_Term_Cannot_Scroll; int *tt_Term_Cannot_Insert; static void init_tt_hooks (void) { tt_beep = msw_beep; tt_write_string = msw_write_string; tt_get_screen_size = msw_get_display_size; tt_set_color = msw_set_color; tt_set_mono = msw_set_mono; tt_Ignore_Beep = &MSW_Ignore_Beep; tt_Use_Ansi_Colors = &MSW_Use_Ansi_Colors; tt_Term_Cannot_Scroll= &MSW_Term_Cannot_Scroll; tt_Term_Cannot_Insert= &MSW_Term_Cannot_Insert; } static void msw_get_terminfo (void) { SLsmg_Term_Type tt; init_tt_hooks (); MSW_Screen_Cols = 80; MSW_Screen_Rows = 24; (void) jed_add_init_slang_hook (msw_init_slang); /* Set this so that main will not try to read from stdin. It is quite * likely that this is started from a menu or something. */ Stdin_Is_TTY = -1; /* init hooks */ X_Update_Open_Hook = msw_update_open; X_Update_Close_Hook = msw_update_close; X_Suspend_Hook = msw_suspend; /* X_Argc_Argv_Hook = X_eval_command_line; */ X_Define_Keys_Hook = msw_define_xkeys; SLang_Interrupt = msw_check_kbd; X_Init_Term_Hook = msw_init_term; if (Batch) return; memset ((char *) &tt, 0, sizeof (SLsmg_Term_Type)); tt.tt_normal_video = msw_normal_video; tt.tt_set_scroll_region = msw_set_scroll_region; tt.tt_goto_rc = msw_goto_rc; tt.tt_reverse_index = msw_reverse_index; tt.tt_reset_scroll_region = msw_reset_scroll_region; tt.tt_delete_nlines = msw_delete_nlines; tt.tt_cls = msw_cls; tt.tt_del_eol = msw_del_eol; tt.tt_smart_puts = msw_smart_puts; tt.tt_flush_output = msw_flush_output; tt.tt_reset_video = msw_reset_video; tt.tt_init_video = msw_init_video; tt.tt_screen_rows = &MSW_Screen_Rows; tt.tt_screen_cols = &MSW_Screen_Cols; tt.tt_term_cannot_scroll = &MSW_Term_Cannot_Scroll; SLsmg_set_terminal_info (&tt); } void (*tt_get_terminfo)(void) = msw_get_terminfo; int (*X_Argc_Argv_Hook)(int, char **) = NULL;