1 module unde.global_state; 2 3 import unde.lib; 4 import unde.lsblk; 5 import unde.clickable; 6 import unde.path_mnt; 7 import unde.font; 8 import unde.marks; 9 import unde.slash; 10 import unde.command_line.lib; 11 import unde.file_manager.events; 12 import unde.keybar.lib; 13 import unde.keybar.settings; 14 import unde.guitk.lib; 15 16 import std.format; 17 import std.conv; 18 import std.stdio; 19 import core.stdc.stdlib; 20 import core.stdc..string; 21 import core.stdc.errno; 22 import core.thread; 23 version (Posix) 24 { 25 import core.sys.posix.unistd: fork; 26 } 27 import core.sys.posix.sys.ioctl; 28 import std..string; 29 import std.concurrency; 30 import std.datetime; 31 import std.math; 32 import std.container.slist; 33 import std.regex; 34 import std.exception; 35 import std.process; 36 37 import berkeleydb.all; 38 import derelict.sdl2.sdl; 39 import derelict.sdl2.ttf; 40 import derelict.sdl2.image; 41 42 version (Windows) 43 { 44 struct winsize 45 { 46 int ws_col; 47 int ws_row; 48 int ws_xpixel; 49 int ws_ypixel; 50 } 51 } 52 53 public import core.sys.posix.sys.types; 54 55 import std.file; 56 57 struct Texture_Tick 58 { 59 int w, h; 60 SDL_Rect[] chars; 61 SDL_Texture* texture; 62 long tick; 63 } 64 65 mixin template init_deinitBDB(bool main_thread = false) 66 { 67 DbEnv dbenv; 68 Db db_map; 69 Db db_marks; 70 Db db_commands; 71 Db db_command_output; 72 73 void initBDB(bool force_recover = false) 74 { 75 string home = environment["HOME"]; 76 version(Windows) 77 { 78 if (!home.startsWith("C:\\cygwin\\home") && 79 !home.startsWith("D:\\cygwin\\home") && 80 !home.startsWith("C:\\cygwin64\\home") && 81 !home.startsWith("D:\\cygwin64\\home")) 82 { 83 throw new Exception("Please run under Cygwin environment. Read README."); 84 } 85 } 86 87 try{ 88 mkdir(home ~ "/.unde"); 89 } catch (Exception file) 90 { 91 } 92 93 try{ 94 mkdir(home ~ "/.unde/bdb/"); 95 } catch (Exception file) 96 { 97 } 98 99 bool recover = force_recover; 100 bool goto_recover = false; 101 recover: 102 if (main_thread) 103 { 104 if (recover) 105 { 106 writefln("Open Database. Recover mode enabled. Please wait..."); 107 } 108 else 109 { 110 writefln("Open Database. If it takes long, try `./unde --force_recover`"); 111 } 112 } 113 114 dbenv = new DbEnv(0); 115 116 dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); 117 dbenv.set_memory_max(16*1024*1024); 118 dbenv.set_lk_detect(DB_LOCK_MAXLOCKS); 119 120 uint env_flags = DB_CREATE | /* Create the environment if it does 121 * not already exist. */ 122 DB_INIT_TXN | /* Initialize transactions */ 123 DB_INIT_LOCK | /* Initialize locking. */ 124 DB_INIT_LOG | /* Initialize logging */ 125 DB_INIT_MPOOL| /* Initialize the in-memory cache. */ 126 (recover?DB_RECOVER:0); 127 128 dbenv.open(home ~ "/.unde/bdb/", env_flags, octal!666); 129 130 db_map = new Db(dbenv, 0); 131 db_map.open(null, "map.db", null, DB_BTREE, DB_CREATE | 132 DB_AUTO_COMMIT /*| DB_MULTIVERSION*/, octal!600); 133 134 db_marks = new Db(dbenv, 0); 135 db_marks.open(null, "marks.db", null, DB_BTREE, DB_CREATE | 136 DB_AUTO_COMMIT /*| DB_MULTIVERSION*/, octal!600); 137 138 db_commands = new Db(dbenv, 0); 139 db_commands.open(null, "commands.db", null, DB_BTREE, DB_CREATE | 140 DB_AUTO_COMMIT /*| DB_MULTIVERSION*/, octal!600); 141 142 db_command_output = new Db(dbenv, 0); 143 db_command_output.open(null, "command_output.db", null, DB_BTREE, DB_CREATE | 144 DB_AUTO_COMMIT /*| DB_MULTIVERSION*/, octal!600); 145 146 txn = dbenv.txn_begin(null); 147 148 try 149 { 150 Dbt key, data; 151 string opened_str = "opened"; 152 key = opened_str; 153 154 int opened = 0; 155 156 if (!main_thread || !recover) 157 { 158 auto res = db_marks.get(txn, &key, &data); 159 if (res == 0) 160 { 161 opened = data.to!int; 162 } 163 } 164 165 if (main_thread && opened != 0 && !recover) 166 { 167 recover = true; 168 txn.abort(); 169 txn = null; 170 db_command_output.close(); 171 db_commands.close(); 172 db_marks.close(); 173 db_map.close(); 174 dbenv.close(); 175 goto recover; 176 } 177 178 opened++; 179 data = opened; 180 auto res = db_marks.put(txn, &key, &data); 181 if (res != 0) 182 { 183 throw new Exception("Oh, no, can't to write new value of opened"); 184 } 185 } 186 catch (Exception exp) 187 { 188 goto_recover = true; 189 } 190 191 if (main_thread && !recover && goto_recover) 192 { 193 recover = true; 194 txn.abort(); 195 txn = null; 196 db_command_output.close(); 197 db_commands.close(); 198 db_marks.close(); 199 db_map.close(); 200 dbenv.close(); 201 goto recover; 202 } 203 204 txn.commit(); 205 txn = null; 206 207 if (main_thread) 208 { 209 writefln("Clean logs."); 210 dbenv.log_archive(DB_ARCH_REMOVE); 211 writefln("Database opened."); 212 } 213 } 214 215 void deInitBDB() 216 { 217 if (txn) 218 { 219 txn.abort(); 220 txn = null; 221 } 222 txn = dbenv.txn_begin(null); 223 try 224 { 225 Dbt key, data; 226 string opened_str = "opened"; 227 key = opened_str; 228 229 int opened = 0; 230 231 auto res = db_marks.get(txn, &key, &data); 232 if (res == 0) 233 { 234 opened = data.to!int; 235 } 236 237 opened--; 238 239 data = opened; 240 res = db_marks.put(txn, &key, &data); 241 if (res != 0) 242 { 243 throw new Exception("Oh, no, can't to write new value of opened"); 244 } 245 } 246 catch (Exception exp) 247 { 248 } 249 250 txn.commit(); 251 txn = null; 252 253 db_command_output.close(); 254 db_commands.close(); 255 db_marks.close(); 256 db_map.close(); 257 dbenv.close(); 258 dbenv = null; 259 db_command_output = null; 260 db_commands = null; 261 db_marks = null; 262 db_map = null; 263 } 264 } 265 266 mixin template recommit() 267 { 268 bool txn_on = true; 269 DbTxn txn; 270 int OIT; // operations in transaction 271 long beginned; 272 SysTime txn_started; 273 274 bool is_time_to_recommit() 275 { 276 if (!txn_on) return false; 277 return OIT > 100 || OIT > 0 && (Clock.currTime() - txn_started) > 200.msecs; 278 } 279 280 void recommit() 281 { 282 if (!txn_on) return; 283 if (OIT > 100 || OIT > 0 && (Clock.currTime() - txn_started) > 200.msecs) 284 { 285 commit(); 286 } 287 if (txn is null) 288 { 289 txn = dbenv.txn_begin(null); 290 txn_started = Clock.currTime(); 291 } 292 } 293 294 void commit() 295 { 296 if (!txn_on) return; 297 //writefln("Tid=%s, OIT=%d, time=%s", thisTid, OIT, Clock.currTime() - txn_started); 298 if (txn !is null) 299 { 300 txn.commit(); 301 txn = null; 302 OIT = 0; 303 } 304 } 305 306 void abort() 307 { 308 //writefln("Tid=%s, OIT=%d, time=%s", thisTid, OIT, Clock.currTime() - txn_started); 309 if (txn !is null) 310 { 311 txn.abort(); 312 txn = null; 313 OIT = 0; 314 } 315 } 316 } 317 318 struct CopyMapInfo 319 { 320 string path; 321 bool[Tid] sent; 322 bool move; 323 Tid from; 324 } 325 326 class ScannerGlobalState 327 { 328 LsblkInfo[string] lsblk; 329 CopyMapInfo[string] copy_map; 330 Tid parent_tid; 331 bool finish; 332 bool one_level; 333 334 mixin init_deinitBDB; 335 mixin recommit; 336 337 this() 338 { 339 initBDB(); 340 } 341 342 ~this() 343 { 344 deInitBDB(); 345 } 346 } 347 348 class FMGlobalState 349 { 350 LsblkInfo[string] lsblk; 351 bool finish; 352 353 mixin init_deinitBDB; 354 mixin recommit; 355 356 this() 357 { 358 initBDB(); 359 } 360 361 ~this() 362 { 363 deInitBDB(); 364 } 365 } 366 367 class CMDGlobalState 368 { 369 bool finish; 370 371 mixin init_deinitBDB; 372 mixin recommit; 373 374 this() 375 { 376 initBDB(); 377 } 378 379 ~this() 380 { 381 deInitBDB(); 382 } 383 } 384 385 enum NameType 386 { 387 CreateDirectory, 388 Copy, 389 Move 390 } 391 392 struct EnterName 393 { 394 NameType type; 395 string name; 396 int pos; 397 } 398 399 struct AnimationInfo 400 { 401 NameType type; 402 int stage; 403 string parent; 404 bool from_calculated; 405 bool to_calculated; 406 SDL_Rect from; 407 SDL_Rect to; 408 long last_frame_time; 409 double frame = 0.0; 410 } 411 412 struct RepeatStuffs 413 { 414 long start_press; 415 long last_process; 416 SDL_Event event; 417 } 418 419 struct ConsoleMessage 420 { 421 SDL_Color color; 422 string message; 423 uint from; 424 SDL_Texture *texture; 425 int w, h; 426 } 427 428 enum State 429 { 430 FileManager, 431 ImageViewer, 432 TextViewer 433 } 434 435 struct Image_Viewer_State{ 436 PathMnt path; 437 SDL_Rect rect; 438 Texture_Tick *texture_tick; 439 RectSize rectsize; 440 441 ssize_t level; 442 ssize_t[] positions; 443 string[][] files; 444 ssize_t sel; 445 string[] selections; 446 447 long last_image_cache_use; 448 Texture_Tick[string] image_cache; 449 }; 450 451 struct Text_Viewer_State{ 452 PathMnt path; 453 int fontsize = 9; 454 bool wraplines; 455 int x, y; 456 RectSize rectsize; 457 458 ssize_t level; 459 ssize_t[] positions; 460 string[][] files; 461 ssize_t sel; 462 string[] selections; 463 464 long last_redraw; 465 SDL_Texture *texture; 466 467 ssize_t mouse_offset; 468 ssize_t start_selection; 469 ssize_t end_selection; 470 ssize_t first_click; 471 472 Font font; 473 } 474 475 struct CmdOutPos 476 { 477 ulong cmd_id; 478 ulong out_id; 479 ssize_t pos; 480 481 int opCmp(CmdOutPos rhs) 482 { 483 if (cmd_id > rhs.cmd_id) 484 return 1; 485 else if (cmd_id < rhs.cmd_id) 486 return -1; 487 else 488 { 489 if (out_id > rhs.out_id) 490 return 1; 491 else if (out_id < rhs.out_id) 492 return -1; 493 else 494 { 495 if (pos > rhs.pos) 496 return 1; 497 if (pos < rhs.pos) 498 return -1; 499 else 500 return 0; 501 } 502 } 503 } 504 505 } 506 507 struct Command_Line_State{ 508 int fontsize = 9; 509 bool font_changed; 510 511 bool enter; 512 string command; 513 string complete; 514 string edited_command; 515 ssize_t pos; 516 517 string cwd; 518 ulong hist_cmd_id; 519 ssize_t hist_pos; 520 521 ulong nav_skip_cmd_id; 522 ulong nav_cmd_id; 523 ulong nav_out_id; 524 525 CmdOutPos mouse; 526 CmdOutPos first_click; 527 CmdOutPos start_selection; 528 CmdOutPos end_selection; 529 530 ssize_t cmd_mouse_pos; 531 ssize_t cmd_first_click; 532 ssize_t cmd_start_selection = -1; 533 ssize_t cmd_end_selection = -1; 534 SDL_Rect cmd_rect; 535 536 double mouse_rel_y; 537 long y; 538 long neg_y; 539 540 long last_enter; 541 542 bool terminal; 543 544 bool just_started_input; 545 546 long last_redraw; 547 SDL_Texture *texture; 548 549 Tid command_in_focus_tid; 550 ulong command_in_focus_id; 551 552 long last_left_click; 553 long last_right_click; 554 long last_ctrl; 555 int moved_while_click; 556 557 void delegate() on_click; 558 559 bool ctrl_mode; 560 bool search_mode; 561 string search; 562 563 winsize ws; 564 } 565 566 enum Modifiers 567 { 568 Left_Ctrl = 0x0001, 569 Right_Ctrl = 0x0002, 570 Left_Shift = 0x0004, 571 Right_Shift= 0x0008, 572 Left_Alt = 0x0010, 573 Right_Alt = 0x0020, 574 CapsLock = 0x0040, 575 Left_Win = 0x0080, 576 Right_Win = 0x0100, 577 Space = 0x0200, 578 Menu = 0x0400, 579 ScrollLock = 0x0800, 580 } 581 582 class GlobalState 583 { 584 SDL_Window* window; 585 SDL_Renderer* renderer; 586 SDL_Texture* surf_texture; 587 bool finish = false; 588 string start_cwd; 589 string[] args; 590 bool restart; 591 uint frame; //Frame which renders 592 uint time; //Time from start of program in ms 593 immutable msize = 128; 594 595 string desktop; 596 string[string] mime_applications; 597 State state; 598 Image_Viewer_State image_viewer; 599 Text_Viewer_State text_viewer; 600 Command_Line_State command_line; 601 KeyBar_Buttons keybar; 602 UIPage[string] uipages; 603 604 CoordinatesPlusScale screen; 605 double mousex, mousey; 606 int mouse_screen_x, mouse_screen_y; 607 long last_mouse_down; 608 long last_left_click; 609 long last_right_click; 610 long last_middle_click; 611 long last_key_press; 612 int key_press; 613 int moved_while_click; 614 uint flags; 615 uint mouse_buttons; 616 LsblkInfo[string] lsblk; 617 618 SList!Clickable clickable_list; 619 SList!Clickable new_clickable_list; 620 621 SList!Clickable double_clickable_list; 622 SList!Clickable new_double_clickable_list; 623 624 SList!Clickable right_clickable_list; 625 SList!Clickable new_right_clickable_list; 626 627 SList!Clickable double_right_clickable_list; 628 SList!Clickable new_double_right_clickable_list; 629 630 SList!Clickable middle_clickable_list; 631 SList!Clickable new_middle_clickable_list; 632 633 ulong msg_stamp; // RU: Время ранее которого сообщения считать просмотренными 634 ulong last_escape; 635 636 Selection[] selection_list; 637 DRect[string] selection_hash; 638 bool[string] selection_sub; 639 int selection_lsof; //list size on finish 640 int selection_finish; 641 int selection_stage = 2; 642 643 ConsoleMessage[] messages; 644 645 bool[string] interface_flags; 646 bool dirty; 647 bool redraw_fast; 648 649 Tid[] scanners; 650 Tid[string] rescanners; 651 string[][Tid] removers; 652 string[][Tid] copiers; 653 string[][Tid] movers; 654 string[][Tid] changers_rights; 655 string[Tid] commands; 656 ulong[Tid] delete_commands; 657 Tid[ulong] tid_by_command_id; 658 Pid[] pids; 659 CopyMapInfo[string] copy_map; 660 EnterName[string] enter_names; 661 AnimationInfo[string] animation_info; 662 RepeatStuffs repeat; 663 664 bool mark; 665 bool gomark; 666 bool unmark; 667 ushort modifiers; 668 @property bool ctrl() { return (modifiers & (Modifiers.Left_Ctrl | Modifiers.Right_Ctrl)) != 0; } 669 @property bool shift() { return (modifiers & (Modifiers.Left_Shift | Modifiers.Right_Shift)) != 0; } 670 @property bool alt() { return (modifiers & (Modifiers.Left_Alt)) != 0; } 671 @property bool alt_gr() { return (modifiers & (Modifiers.Right_Alt)) != 0; } 672 bool shift_copy_or_move; 673 DRect current_path_rect; 674 string current_path; 675 string full_current_path; 676 string main_path = SL; 677 PathMnt path; 678 DRect apply_rect; 679 SortType sort; 680 CoordinatesPlusScale surf; 681 SDL_Texture* texture; 682 SDL_Texture* texture_white; 683 SDL_Texture* texture_black; 684 SDL_Texture* texture_blue; 685 SDL_Texture* texture_cursor; 686 SDL_Texture* texture_gray; 687 Gradient grad; 688 689 void createWindow() 690 { 691 //The window we'll be rendering to 692 window = SDL_CreateWindow( 693 "unDE", // window title 694 SDL_WINDOWPOS_UNDEFINED, // initial x position 695 SDL_WINDOWPOS_UNDEFINED, // initial y position 696 0, // width, in pixels 697 0, // height, in pixels 698 SDL_WINDOW_FULLSCREEN_DESKTOP | 699 SDL_WINDOW_RESIZABLE // flags 700 ); 701 if( window == null ) 702 { 703 throw new Exception(format("Error while create window: %s", 704 SDL_GetError().to!string())); 705 } 706 } 707 708 void createRenderer() 709 { 710 /* To render we need only renderer (which connected to window) and 711 surfaces to draw it */ 712 renderer = SDL_CreateRenderer( 713 window, 714 -1, 715 SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE 716 ); 717 if (!renderer) 718 { 719 writefln("Error while create accelerated renderer: %s", 720 SDL_GetError().to!string()); 721 renderer = SDL_CreateRenderer( 722 window, 723 -1, 724 SDL_RENDERER_TARGETTEXTURE 725 ); 726 } 727 if (!renderer) 728 { 729 throw new Exception(format("Error while create renderer: %s", 730 SDL_GetError().to!string())); 731 } 732 733 int r = SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); 734 if (r < 0) 735 { 736 throw new Exception( 737 format("Error while set render draw blend mode: %s", 738 SDL_GetError().to!string())); 739 } 740 741 SDL_bool res = SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"); 742 if (!res) 743 { 744 throw new Exception( 745 format("Can't set filter mode")); 746 } 747 } 748 749 void createTextures() 750 { 751 SDL_Surface* surface = SDL_CreateRGBSurface(0, 752 1, 753 1, 754 32, 0x00FF0000, 0X0000FF00, 0X000000FF, 0XFF000000); 755 756 (cast(uint*) surface.pixels)[0] = 0x80FFFFFF; 757 758 texture_white = 759 SDL_CreateTextureFromSurface(renderer, surface); 760 761 (cast(uint*) surface.pixels)[0] = 0xAA000000; 762 763 texture_black = 764 SDL_CreateTextureFromSurface(renderer, surface); 765 766 (cast(uint*) surface.pixels)[0] = 0x800000FF; 767 768 texture_blue = 769 SDL_CreateTextureFromSurface(renderer, surface); 770 771 (cast(uint*) surface.pixels)[0] = 0xFFA0A0FF; 772 773 texture_cursor = 774 SDL_CreateTextureFromSurface(renderer, surface); 775 776 (cast(uint*) surface.pixels)[0] = 0x80808080; 777 778 texture_gray = 779 SDL_CreateTextureFromSurface(renderer, surface); 780 781 text_viewer.texture = SDL_CreateTexture(renderer, 782 SDL_PIXELFORMAT_ARGB8888, 783 SDL_TEXTUREACCESS_TARGET, 784 screen.w, 785 screen.h); 786 if( !text_viewer.texture ) 787 { 788 throw new Exception(format("Error while creating text_viewer.texture: %s", 789 SDL_GetError().to!string() )); 790 } 791 792 command_line.texture = SDL_CreateTexture(renderer, 793 SDL_PIXELFORMAT_ARGB8888, 794 SDL_TEXTUREACCESS_TARGET, 795 screen.w, 796 screen.h); 797 if( !command_line.texture ) 798 { 799 throw new Exception(format("Error while creating command_line.texture: %s", 800 SDL_GetError().to!string() )); 801 } 802 803 SDL_FreeSurface(surface); 804 } 805 806 void initSDL() 807 { 808 DerelictSDL2.load(); 809 810 if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 ) 811 { 812 throw new Exception(format("Error while SDL initializing: %s", 813 SDL_GetError().to!string() )); 814 } 815 816 createWindow(); 817 createRenderer(); 818 819 SDL_GetWindowSize(window, &screen.w, &screen.h); 820 screen.w -= 192; 821 822 createTextures(); 823 824 surf.w = 2*screen.w; 825 surf.h = 2*screen.h; 826 surf_texture = SDL_CreateTexture(renderer, 827 SDL_PIXELFORMAT_ARGB8888, 828 SDL_TEXTUREACCESS_TARGET, 829 surf.w, 830 surf.h); 831 if( !surf_texture ) 832 { 833 throw new Exception(format("Error while creating surf_texture: %s", 834 SDL_GetError().to!string() )); 835 } 836 837 texture = SDL_CreateTexture(renderer, 838 SDL_PIXELFORMAT_ARGB8888, 839 SDL_TEXTUREACCESS_TARGET, 840 surf.w, 841 surf.h); 842 if( !texture ) 843 { 844 throw new Exception(format("Error while creating surf_texture: %s", 845 SDL_GetError().to!string() )); 846 } 847 } 848 849 void deInitSDL() 850 { 851 SDL_DestroyTexture(text_viewer.texture), 852 SDL_DestroyTexture(texture_blue); 853 SDL_DestroyTexture(texture_black); 854 SDL_DestroyTexture(texture_white); 855 SDL_DestroyTexture(texture); 856 SDL_DestroyTexture(surf_texture); 857 SDL_DestroyRenderer(renderer); 858 SDL_DestroyWindow(window); 859 SDL_Quit(); 860 } 861 862 void initSDLImage() 863 { 864 DerelictSDL2Image.load(); 865 866 auto flags = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF; 867 int initted = IMG_Init(flags); 868 if((initted&flags) != flags) { 869 if (!(IMG_INIT_JPG & initted)) 870 writefln("IMG_Init: Failed to init required jpg support!"); 871 if (!(IMG_INIT_PNG & initted)) 872 writefln("IMG_Init: Failed to init required png support!"); 873 if (!(IMG_INIT_TIF & initted)) 874 writefln("IMG_Init: Failed to init required tif support!"); 875 throw new Exception(format("IMG_Init: %s\n", 876 IMG_GetError().to!string())); 877 } 878 } 879 880 void initSDLTTF() 881 { 882 text_viewer.font = new Font(renderer); 883 } 884 885 void initAllSDLLibs() 886 { 887 initSDL(); 888 initSDLImage(); 889 initSDLTTF(); 890 } 891 892 void deInitAllSDLLibs() 893 { 894 IMG_Quit(); 895 deInitSDL(); 896 } 897 898 mixin init_deinitBDB!true; 899 mixin recommit; 900 901 void initGradient() 902 { 903 /* Gradient Initialize */ 904 grad.add(SDL_Color( 0, 255, 255, 255), 0.0); 905 grad.add(SDL_Color( 0, 255, 0, 255), 3.0); 906 grad.add(SDL_Color(255, 255, 0, 255), 6.0); 907 grad.add(SDL_Color(255, 0, 0, 255), 9.0); 908 grad.add(SDL_Color(255, 0, 255, 255), 12.0); 909 } 910 911 void initScreenAndSurf() 912 { 913 path = PathMnt(SL); 914 apply_rect = DRect(0, 0, 1024*1024, 1024*1024); 915 916 screen.x = 0; 917 screen.y = 0; 918 screen.scale = 2 * 1024*1024 / screen.w; 919 920 surf.x = 0; 921 surf.y = 0; 922 surf.scale = 1; 923 } 924 925 void loadMimeApplications() 926 { 927 try 928 { 929 string home = environment["HOME"]; 930 auto file = File(home ~ "/.unde/mime"); 931 foreach (line; file.byLine()) 932 { 933 auto match = matchFirst(line, regex(`([^ ]*) *= *(.*)`)); 934 if (match) 935 { 936 mime_applications[match[1].idup()] = match[2].idup(); 937 } 938 } 939 } 940 catch(ErrnoException e) 941 { 942 writefln("~/.unde/mime NOT FOUND"); 943 writefln(q{Example of line "text/plain = gvim"}); 944 } 945 } 946 947 void getCurrentDesktop() 948 { 949 string current_desktop = "current_desktop"; 950 Dbt key = current_desktop; 951 Dbt data; 952 953 auto res = db_marks.get(null, &key, &data); 954 955 desktop = "1"; 956 if (res == 0) 957 { 958 desktop = data.to!(string).idup(); 959 } 960 961 if (desktop.length != 1 || desktop[0] < '0' || desktop[0] > '9') 962 { 963 writefln("WARNING! current_desktop = %s", desktop); 964 desktop = "1"; 965 } 966 967 go_mark(this, desktop); 968 } 969 970 this(bool force_recover = false) 971 { 972 start_cwd = getcwd(); 973 txn_on = false; 974 msg_stamp = Clock.currTime().toUnixTime(); 975 initBDB(force_recover); 976 initAllSDLLibs(); 977 initGradient(); 978 initScreenAndSurf(); 979 loadMimeApplications(); 980 .lsblk(this.lsblk); 981 getCurrentDesktop(); 982 update_winsize(this); 983 keybar = new KeyBar_Buttons(this, renderer, start_cwd); 984 setup_keybar_filemanager_default(this); 985 uipages["keybar_settings"] = create_keybar_settings_ui(this); 986 } 987 988 ~this() 989 { 990 deInitBDB(); 991 deInitAllSDLLibs(); 992 if (restart) 993 { 994 version (Posix) 995 { 996 writefln("Restart"); 997 int r = fork(); 998 if (r < 0) 999 { 1000 throw new Exception("fork() error: " ~ fromStringz(strerror(errno)).idup()); 1001 } 1002 else if (r == 0) 1003 { 1004 Thread.sleep(2.seconds); 1005 chdir(start_cwd); 1006 execv(args[0], args); 1007 assert(0); 1008 } 1009 } 1010 else version (Windows) 1011 { 1012 writefln("Restart in windows version not supported. Exit."); 1013 } 1014 } 1015 } 1016 } 1017