Allen Webster 2020-01-22 14:02:51 -08:00
commit f41fe45c92
15 changed files with 187 additions and 138 deletions

View File

@ -587,6 +587,54 @@ enum{
Tier_COUNT, Tier_COUNT,
}; };
function void
package_for_arch(Arena *arena, u32 arch, char *cdir, char *build_dir, char *pack_dir, i32 tier, char *tier_name, char *current_dist_tier, u32 flags, char** dist_files, i32 dist_file_count){
char *arch_name = arch_names[arch];
char *parent_dir = fm_str(arena, current_dist_tier, "_", arch_name);
char *dir = fm_str(arena, parent_dir, SLASH "4coder");
char *zip_dir = fm_str(arena, pack_dir, SLASH, tier_name, "_", arch_name);
printf("\nbuild: %s_%s\n", tier_name, arch_name);
printf("parent_dir: %s\n", parent_dir);
printf("dir: %s\n", dir);
printf("zip_dir: %s\n", zip_dir);
fflush(stdout);
buildsuper(arena, cdir, fm_str(arena, default_custom_target), arch);
build_main(arena, cdir, false, flags, arch);
fm_clear_folder(parent_dir);
fm_make_folder_if_missing(arena, parent_dir);
fm_make_folder_if_missing(arena, dir);
fm_copy_file(fm_str(arena, build_dir, "/4ed" EXE), fm_str(arena, dir, "/4ed" EXE));
fm_copy_file(fm_str(arena, build_dir, "/4ed_app" DLL), fm_str(arena, dir, "/4ed_app" DLL));
fm_copy_file(fm_str(arena, build_dir, "/custom_4coder" DLL), fm_str(arena, dir, "/custom_4coder" DLL));
if (tier == Tier_Demo){
dist_file_count -= 1;
}
for (i32 j = 0; j < dist_file_count; j += 1){
fm_copy_all(dist_files[j], dir);
}
if (tier == Tier_Super){
char *custom_src_dir = fm_str(arena, cdir, SLASH, "custom");
char *custom_dst_dir = fm_str(arena, dir, SLASH, "custom");
// HACK(yuval): make_folder_if_missing seems to cause a second custom folder to be created inside the custom folder on macOS.
//if (This_OS != Platform_Mac){
fm_make_folder_if_missing(arena, custom_dst_dir);
//}
fm_copy_all(custom_src_dir, custom_dst_dir);
}
char *dist_name = get_4coder_dist_name(arena, This_OS, tier_name, arch);
char *zip_name = fm_str(arena, zip_dir, SLASH, dist_name, ".zip");
fm_make_folder_if_missing(arena, zip_dir);
fm_zip(parent_dir, "4coder", zip_name);
}
internal void internal void
package(Arena *arena, char *cdir){ package(Arena *arena, char *cdir){
// NOTE(allen): meta // NOTE(allen): meta
@ -615,48 +663,17 @@ package(Arena *arena, char *cdir){
Temp_Memory temp = begin_temp(arena); Temp_Memory temp = begin_temp(arena);
char *current_dist_tier = fm_str(arena, ".." SLASH "current_dist_", tier_name); char *current_dist_tier = fm_str(arena, ".." SLASH "current_dist_", tier_name);
for (u32 arch = 0; arch < Arch_COUNT; ++arch){ i32 arch_count = Arch_COUNT;
char *arch_name = arch_names[arch]; u32 arch_array[2] = {
char *parent_dir = fm_str(arena, current_dist_tier, "_", arch_name); Arch_X64,
char *dir = fm_str(arena, parent_dir, SLASH "4coder"); Arch_X86,
char *zip_dir = fm_str(arena, pack_dir, SLASH, tier_name, "_", arch_name); };
if (This_OS == Platform_Mac){
printf("\nbuild: %s_%s\n", tier_name, arch_name); arch_count = 1;
printf("parent_dir: %s\n", parent_dir); }
printf("dir: %s\n", dir); for (u32 arch_ind = 0; arch_ind < arch_count; ++arch_ind){
printf("zip_dir: %s\n", zip_dir); u32 arch = arch_array[arch_ind];
fflush(stdout); package_for_arch(arena, arch, cdir, build_dir, pack_dir, i, tier_name, current_dist_tier, flags, dist_files, ArrayCount(dist_files));
buildsuper(arena, cdir, fm_str(arena, default_custom_target), arch);
build_main(arena, cdir, false, flags, arch);
fm_make_folder_if_missing(arena, parent_dir);
fm_clear_folder(parent_dir);
fm_make_folder_if_missing(arena, dir);
fm_copy_file(fm_str(arena, build_dir, "/4ed" EXE), fm_str(arena, dir, "/4ed" EXE));
fm_copy_file(fm_str(arena, build_dir, "/4ed_app" DLL), fm_str(arena, dir, "/4ed_app" DLL));
fm_copy_file(fm_str(arena, build_dir, "/custom_4coder" DLL), fm_str(arena, dir, "/custom_4coder" DLL));
i32 dist_file_count = ArrayCount(dist_files);
if (i == Tier_Demo){
dist_file_count -= 1;
}
for (i32 j = 0; j < dist_file_count; j += 1){
fm_copy_all(dist_files[j], dir);
}
if (i == Tier_Super){
char *custom_src_dir = fm_str(arena, cdir, SLASH, "custom");
char *custom_dst_dir = fm_str(arena, dir, SLASH, "custom");
fm_make_folder_if_missing(arena, custom_dst_dir);
fm_copy_all(custom_src_dir, custom_dst_dir);
}
char *dist_name = get_4coder_dist_name(arena, This_OS, tier_name, arch);
char *zip_name = fm_str(arena, zip_dir, SLASH, dist_name, ".zip");
fm_make_folder_if_missing(arena, zip_dir);
fm_zip(parent_dir, "4coder", zip_name);
} }
end_temp(temp); end_temp(temp);

4
bin/package-mac.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
chmod 777 bin/build-mac.sh
bin/build-mac.sh "-DPACKAGE"

View File

@ -34,6 +34,32 @@ parse_extension_line_to_extension_list(Application_Links *app,
//////////////////////////////// ////////////////////////////////
function void
setup_built_in_mapping(Application_Links *app, String_Const_u8 name, Mapping *mapping, i64 global_id, i64 file_id, i64 code_id){
Thread_Context *tctx = get_thread_context(app);
if (string_match(name, string_u8_litexpr("default"))){
mapping_release(tctx, mapping);
mapping_init(tctx, mapping);
setup_default_mapping(mapping, global_id, file_id, code_id);
}
else if (string_match(name, string_u8_litexpr("mac-default"))){
mapping_release(tctx, mapping);
mapping_init(tctx, mapping);
setup_mac_mapping(mapping, global_id, file_id, code_id);
}
else if (string_match(name, string_u8_litexpr("choose"))){
mapping_release(tctx, mapping);
mapping_init(tctx, mapping);
#if OS_MAC
setup_mac_mapping(mapping, global_id, file_id, code_id);
#else
setup_default_mapping(mapping, global_id, file_id, code_id);
#endif
}
}
////////////////////////////////
function Error_Location function Error_Location
get_error_location(Application_Links *app, u8 *base, u8 *pos){ get_error_location(Application_Links *app, u8 *base, u8 *pos){
ProfileScope(app, "get error location"); ProfileScope(app, "get error location");

View File

@ -11,8 +11,6 @@
// NOTE(allen): Users can declare their own managed IDs here. // NOTE(allen): Users can declare their own managed IDs here.
#include "4coder_default_map.cpp"
#include "4coder_mac_map.cpp"
#include "generated/managed_id_metadata.cpp" #include "generated/managed_id_metadata.cpp"
void void
@ -34,30 +32,6 @@ custom_layer_init(Application_Links *app){
setup_default_mapping(&framework_mapping, mapid_global, mapid_file, mapid_code); setup_default_mapping(&framework_mapping, mapid_global, mapid_file, mapid_code);
} }
function void
setup_built_in_mapping(Application_Links *app, String_Const_u8 name, Mapping *mapping, i64 global_id, i64 file_id, i64 code_id){
Thread_Context *tctx = get_thread_context(app);
if (string_match(name, string_u8_litexpr("default"))){
mapping_release(tctx, mapping);
mapping_init(tctx, mapping);
setup_default_mapping(mapping, global_id, file_id, code_id);
}
else if (string_match(name, string_u8_litexpr("mac-default"))){
mapping_release(tctx, mapping);
mapping_init(tctx, mapping);
setup_mac_mapping(mapping, global_id, file_id, code_id);
}
else if (string_match(name, string_u8_litexpr("choose"))){
mapping_release(tctx, mapping);
mapping_init(tctx, mapping);
#if OS_MAC
setup_mac_mapping(mapping, global_id, file_id, code_id);
#else
setup_default_mapping(mapping, global_id, file_id, code_id);
#endif
}
}
#endif //FCODER_DEFAULT_BINDINGS #endif //FCODER_DEFAULT_BINDINGS
// BOTTOM // BOTTOM

View File

@ -501,9 +501,14 @@ default_4coder_initialize(Application_Links *app, String_Const_u8_Array file_nam
#define M \ #define M \
"Welcome to " VERSION "\n" \ "Welcome to " VERSION "\n" \
"If you're new to 4coder there are some tutorials at http://4coder.net/tutorials.html\n" \ "If you're new to 4coder there is a built in tutorial\n" \
"Use the key combination [ X Alt ] (on mac [ X Control ])\n" \
"Type in 'hms_demo_tutorial' and press enter\n" \
"\n" \
"Direct bug reports and feature requests to https://github.com/4coder-editor/4coder/issues\n" \ "Direct bug reports and feature requests to https://github.com/4coder-editor/4coder/issues\n" \
"\n" \
"Other questions and discussion can be directed to editor@4coder.net or 4coder.handmade.network\n" \ "Other questions and discussion can be directed to editor@4coder.net or 4coder.handmade.network\n" \
"\n" \
"The change log can be found in CHANGES.txt\n" \ "The change log can be found in CHANGES.txt\n" \
"\n" "\n"
print_message(app, string_u8_litexpr(M)); print_message(app, string_u8_litexpr(M));

View File

@ -114,11 +114,6 @@ struct Fade_Range_List{
i32 count; i32 count;
}; };
////////////////////////////////
function void
setup_built_in_mapping(Application_Links *app, String_Const_u8 name, Mapping *mapping, i64 global_id, i64 file_id, i64 code_id);
#endif #endif
// BOTTOM // BOTTOM

View File

@ -78,6 +78,8 @@
#include "4coder_token.cpp" #include "4coder_token.cpp"
#include "generated/lexer_cpp.cpp" #include "generated/lexer_cpp.cpp"
#include "4coder_command_map.cpp" #include "4coder_command_map.cpp"
#include "4coder_default_map.cpp"
#include "4coder_mac_map.cpp"
#include "4coder_default_framework_variables.cpp" #include "4coder_default_framework_variables.cpp"
#include "4coder_default_colors.cpp" #include "4coder_default_colors.cpp"
#include "4coder_helper.cpp" #include "4coder_helper.cpp"

View File

@ -33,11 +33,11 @@ static i32 prev_error = 0;
#endif #endif
#define systemf(...) do{ \ #define systemf(...) do{ \
i32 n = snprintf(SF_CMD, sizeof(SF_CMD), __VA_ARGS__); \ i32 n = snprintf(SF_CMD, sizeof(SF_CMD), __VA_ARGS__); \
Assert(n < sizeof(SF_CMD)); \ Assert(n < sizeof(SF_CMD)); \
SYSTEMF_PRINTF("%s\n", SF_CMD); \ SYSTEMF_PRINTF("%s\n", SF_CMD); \
prev_error = system(SF_CMD); \ prev_error = system(SF_CMD); \
if (prev_error != 0) error_state = 1; \ if (prev_error != 0) error_state = 1; \
}while(0) }while(0)
internal void fm_execute_in_dir(char *dir, char *str, char *args); internal void fm_execute_in_dir(char *dir, char *str, char *args);
@ -109,18 +109,18 @@ internal void fm__swap_ptr(char **A, char **B);
#if COMPILER_CL #if COMPILER_CL
#define fm_add_to_line(line, str, ...) do{ \ #define fm_add_to_line(line, str, ...) do{ \
snprintf(line.build_options, \ snprintf(line.build_options, \
line.build_max, "%s "str, \ line.build_max, "%s "str, \
line.build_options_prev, __VA_ARGS__); \ line.build_options_prev, __VA_ARGS__); \
fm__swap_ptr(&line.build_options, &line.build_options_prev); \ fm__swap_ptr(&line.build_options, &line.build_options_prev); \
}while(0) }while(0)
#elif COMPILER_GCC | COMPILER_CLANG #elif COMPILER_GCC | COMPILER_CLANG
#define fm_add_to_line(line, str, ...) do{ \ #define fm_add_to_line(line, str, ...) do{ \
snprintf(line.build_options, line.build_max, "%s " str, \ snprintf(line.build_options, line.build_max, "%s " str, \
line.build_options_prev, ##__VA_ARGS__); \ line.build_options_prev, ##__VA_ARGS__); \
fm__swap_ptr(&line.build_options, &line.build_options_prev); \ fm__swap_ptr(&line.build_options, &line.build_options_prev); \
}while(0) }while(0)
#endif #endif
@ -510,7 +510,7 @@ fm_copy_file(char *file, char *newname){
internal void internal void
fm_copy_all(char *source, char *folder){ fm_copy_all(char *source, char *folder){
fprintf(stdout, "copy %s to %s\n", source, folder); fprintf(stdout, "copy %s to %s\n", source, folder);
systemf("cp -rf %s %s > /dev/null", source, folder); systemf("cp -rf %s/* %s > /dev/null", source, folder);
} }
internal void internal void

View File

@ -86,6 +86,7 @@ setup_mac_mapping(Mapping *mapping, i64 global_id, i64 file_id, i64 code_id){
Bind(snipe_backward_whitespace_or_token_boundary, KeyCode_Backspace, KeyCode_Control); Bind(snipe_backward_whitespace_or_token_boundary, KeyCode_Backspace, KeyCode_Control);
Bind(snipe_forward_whitespace_or_token_boundary, KeyCode_Delete, KeyCode_Control); Bind(snipe_forward_whitespace_or_token_boundary, KeyCode_Delete, KeyCode_Control);
Bind(set_mark, KeyCode_Space, KeyCode_Control); Bind(set_mark, KeyCode_Space, KeyCode_Control);
Bind(set_mark, KeyCode_ForwardSlash, KeyCode_Command);
Bind(replace_in_range, KeyCode_A, KeyCode_Command); Bind(replace_in_range, KeyCode_A, KeyCode_Command);
Bind(copy, KeyCode_C, KeyCode_Command); Bind(copy, KeyCode_C, KeyCode_Command);
Bind(delete_range, KeyCode_D, KeyCode_Command); Bind(delete_range, KeyCode_D, KeyCode_Command);

View File

@ -1,6 +1,6 @@
#define MAJOR 4 #define MAJOR 4
#define MINOR 1 #define MINOR 1
#define PATCH 1 #define PATCH 2
// string // string
#define VN__(a,b,c) #a "." #b "." #c #define VN__(a,b,c) #a "." #b "." #c

View File

@ -11,7 +11,7 @@ CODE_HOME="$(dirname "$LOCATION")"
# Find the most reasonable candidate build file # Find the most reasonable candidate build file
SOURCE="$1" SOURCE="$1"
if [ -z "$SOURCE" ]; then if [ -z "$SOURCE" ]; then
SOURCE="$(readlink -f "$CODE_HOME/4coder_default_bindings.cpp")" SOURCE="$(realpath "$CODE_HOME/4coder_default_bindings.cpp")"
fi fi
# NOTE(yuval): Removed -Wno-writable-strings as it is the same as -Wno-write-strings # NOTE(yuval): Removed -Wno-writable-strings as it is the same as -Wno-write-strings

View File

@ -1,53 +1,30 @@
#!/bin/bash #!/bin/bash
# Store the real CWD # If any command errors, stop the script
REAL_PWD="$PWD" set -e
# Find the code home folder # Store the real CWD
TARGET_FILE="$0" ME="$(realpath "$0")"
cd `dirname $TARGET_FILE` LOCATION="$(dirname "$ME")"
TARGET_FILE=`basename $TARGET_FILE` CODE_HOME="$(dirname "$LOCATION")"
while [ -L "$TARGET_FILE" ]
do
TARGET_FILE=`readlink $TARGET_FILE`
cd `dirname $TARGET_FILE`
TARGET_FILE=`basename $TARGET_FILE`
done
PHYS_DIR=`pwd -P`
SCRIPT_FILE=$PHYS_DIR/$TARGET_FILE
code_home=$(dirname "$SCRIPT_FILE")
# Find the most reasonable candidate build file # Find the most reasonable candidate build file
SOURCE="$1" SOURCE="$1"
if [ -z "$SOURCE" ]; then if [ -z "$SOURCE" ]; then
SOURCE="$code_home/4coder_default_bindings.cpp" SOURCE="$(readlink -f "$CODE_HOME/4coder_default_bindings.cpp")"
fi fi
TARGET_FILE="$SOURCE"
cd `dirname $TARGET_FILE`
TARGET_FILE=`basename $TARGET_FILE`
while [ -L "$TARGET_FILE" ]
do
TARGET_FILE=`readlink $TARGET_FILE`
cd `dirname $TARGET_FILE`
TARGET_FILE=`basename $TARGET_FILE`
done
PHYS_DIR=`pwd -P`
SOURCE=$PHYS_DIR/$TARGET_FILE
# NOTE(yuval): Removed -Wno-writable-strings as it is the same as -Wno-write-strings # NOTE(yuval): Removed -Wno-writable-strings as it is the same as -Wno-write-strings
opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -g" opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -Wno-missing-declarations -Wno-logical-op-parentheses -g"
arch=-m32 arch=-m32
cd "$REAL_PWD"
preproc_file=4coder_command_metadata.i preproc_file=4coder_command_metadata.i
meta_macros="-DMETA_PASS" meta_macros="-DMETA_PASS"
g++ -I"$code_home" $meta_macros $arch $opts $debug -std=gnu++0x "$SOURCE" -E -o $preproc_file clang++ -I"$CODE_HOME" $meta_macros $arch $opts $debug -std=gnu++0x "$SOURCE" -E -o $preproc_file
g++ -I"$code_home" $opts $debug -std=gnu++0x "$code_home/4coder_metadata_generator.cpp" -o metadata_generator clang++ -I"$CODE_HOME" $opts $debug -std=gnu++0x "$CODE_HOME/4coder_metadata_generator.cpp" -o "$CODE_HOME/metadata_generator"
./metadata_generator -R "$code_home" "$PWD/$preproc_file" "$CODE_HOME/metadata_generator" -R "$CODE_HOME" "$PWD/$preproc_file"
g++ -I"$code_home" $arch $opts $debug -std=gnu++0x "$SOURCE" -shared -o custom_4coder.so -fPIC clang++ -I"$CODE_HOME" $arch $opts $debug -std=c++11 "$SOURCE" -shared -o custom_4coder.so -fPIC
rm metadata_generator rm "$CODE_HOME/metadata_generator"
rm $preproc_file rm $preproc_file

View File

@ -324,6 +324,23 @@ mac_error_box(char *msg, b32 shutdown = true){
} }
} }
function void
os_popup_error(char *title, char *message){
// TODO(yuval): Condense this with mac_error_box
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
NSString *title_string = [NSString stringWithUTF8String:title];
NSString *message_string = [NSString stringWithUTF8String:message];
[alert setMessageText:title_string];
[alert setInformativeText:message_string];
[alert runModal];
exit(1);
}
//////////////////////////////// ////////////////////////////////
#if defined(FRED_INTERNAL) #if defined(FRED_INTERNAL)
@ -533,7 +550,7 @@ mac_read_clipboard_contents(Arena *scratch){
mac_vars.clipboard_contents = string_const_u8_push(clip_arena, copy_length); mac_vars.clipboard_contents = string_const_u8_push(clip_arena, copy_length);
[data getBytes:mac_vars.clipboard_contents.str [data getBytes:mac_vars.clipboard_contents.str
length:mac_vars.clipboard_contents.size]; length:mac_vars.clipboard_contents.size];
result = true; result = true;
} }
@ -552,13 +569,13 @@ mac_post_clipboard(Arena *scratch, char *text, i32 len){
NSString *utf8_type = @"public.utf8-plain-text"; NSString *utf8_type = @"public.utf8-plain-text";
NSArray<NSString*> *types_array = [NSArray arrayWithObjects:utf8_type, nil]; NSArray<NSString*> *types_array = [NSArray arrayWithObjects:utf8_type, nil];
[board declareTypes:types_array [board declareTypes:types_array
owner:nil]; owner:nil];
NSString *paste_string = [[NSString alloc] initWithBytes:text NSString *paste_string = [[NSString alloc] initWithBytes:text
length:len length:len
encoding:NSUTF8StringEncoding]; encoding:NSUTF8StringEncoding];
[board setString:paste_string [board setString:paste_string
forType:utf8_type]; forType:utf8_type];
[paste_string release]; [paste_string release];
mac_vars.next_clipboard_is_self = true; mac_vars.next_clipboard_is_self = true;
@ -595,7 +612,9 @@ mac_toggle_fullscreen(void){
- (void)windowDidResize:(NSNotification*)notification{ - (void)windowDidResize:(NSNotification*)notification{
mac_resize(mac_vars.window); mac_resize(mac_vars.window);
[mac_vars.view display]; if (!mac_vars.do_toggle){
[mac_vars.view display];
}
} }
- (void)windowDidMiniaturize:(NSNotification*)notification{ - (void)windowDidMiniaturize:(NSNotification*)notification{
@ -1272,9 +1291,9 @@ main(int arg_count, char **args){
u32 style_mask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; u32 style_mask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable;
mac_vars.window = [[NSWindow alloc] initWithContentRect:initial_frame mac_vars.window = [[NSWindow alloc] initWithContentRect:initial_frame
styleMask:style_mask styleMask:style_mask
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
defer:NO]; defer:NO];
FCoder_Window_Delegate *window_delegate = [[FCoder_Window_Delegate alloc] init]; FCoder_Window_Delegate *window_delegate = [[FCoder_Window_Delegate alloc] init];
[mac_vars.window setDelegate:window_delegate]; [mac_vars.window setDelegate:window_delegate];
@ -1319,9 +1338,9 @@ main(int arg_count, char **args){
// NOTE(yuval): Start the clipboard polling timer // NOTE(yuval): Start the clipboard polling timer
[NSTimer scheduledTimerWithTimeInterval: 0.5 [NSTimer scheduledTimerWithTimeInterval: 0.5
target:mac_vars.view target:mac_vars.view
selector:@selector(check_clipboard) selector:@selector(check_clipboard)
userInfo:nil repeats:YES]; userInfo:nil repeats:YES];
} }
// NOTE(yuval): Initialize the virtul keycodes table // NOTE(yuval): Initialize the virtul keycodes table

View File

@ -6,9 +6,12 @@ https://github.com/4coder-editor/4coder/issues
For questions email: For questions email:
editor@4coder.net editor@4coder.net
Sign up for the newsletter for the most critical 4coder news:
newsletter.4coder.net
Watch the 4coder.handmade.network blog and @AllenWebster4th twitter for news about 4coder. Watch the 4coder.handmade.network blog and @AllenWebster4th twitter for news about 4coder.
For documentation, feature lists, and usage tutorial videos go to: For documentation, feature lists, and more visit the home page:
4coder.net 4coder.net

View File

@ -1,3 +1,29 @@
4.1.2
+ Cursor color changes when recording macro if the theme provides a second cursor color
+ Default custom layer now has a feature for supporting fade ranges as used in pasting and undoing
+ Ability to "partially" paint text with a blend factor to create blends
+ In file lister, typing a slash with a name for a folder that does not exist asks the user if they would like to create a folder
+ Fix: parser in code index recognizes functions with more than one parameter
+ Fix: trying to create a face with a font file that doesn't exist doesn't crash
+ Fix: escaping command documentation lister doesn't crash
+ Fix: lexer generator switched to new macro names Max and Min
+ Fix: implementation for getting previous view iterates from null to the last view in order (instead of the first)
+ Fix: auto-indent when a file with virtual whitespace is saved
+ Fix: can create up to sixteen panels, and doesn't crash when trying to create more
+ Fix: faster text range highlighting
+ Fix: side by side editing a single buffer doesn't scroll the lower view down when insterting lines in the higher view
+ Fix: indentation after paren group is correct
4.1.1
Changes not documented
4.1.0
Initial beta version
**************************************************
**************************************************
New in alpha 4.0.30: New in alpha 4.0.30:
-Mouse events (clicking, scroll wheel, mouse move) can now be bound with modifier keys -Mouse events (clicking, scroll wheel, mouse move) can now be bound with modifier keys
-New and changed commands: -New and changed commands: