1 /* See LICENSE file for copyright and license details. */
11 #include <sys/types.h>
12 #include <sys/resource.h>
29 enum { AskDel
, DAskDel
}; /* delete directory */
43 char dirn
[MAX_P
]; // directory name
44 char high_dir
[MAX_P
]; // highlighted_dir fullpath
45 int dirx
; // position of title
46 size_t hdir
; // highlighted_dir
47 size_t dirc
; // total files in dir
65 /* function declarations */
66 static void print_tb(const char*, int, int, uint16_t, uint16_t);
67 static void printf_tb(int, int, uint16_t, uint16_t, const char*, ...);
68 static void print_status(const char*, ...);
69 static void print_xstatus(char, int);
70 static void print_error(const char*, ...);
71 static void clear(int, int, int, uint16_t);
72 static void clear_status(void);
73 static void clear_error(void);
74 static void clear_pane(int);
75 static char *get_extentions(char*);
76 static char *get_full_path(char*, char*);
77 static char *get_parent(char*);
78 static char *get_file_info(Entry
*);
79 static char *get_file_size(off_t
);
80 static char *get_file_date_time(time_t);
81 static char *get_file_userowner(uid_t
, size_t);
82 static char *get_file_groupowner(gid_t
, size_t);
83 static char *get_file_perm(mode_t
);
84 static int create_new_dir(char*, char*);
85 static int create_new_file(char*, char*);
86 static int delete_ent(char *fullpath
);
87 static int delete_file(char*);
88 static int delete_dir(char*, int);
89 static int check_dir(char*);
90 static int chech_execf(mode_t mode
);
91 static int open_files(char*);
92 static int sort_name(const void *const, const void *const);
93 static void float_to_string(float, char*);
94 static size_t findbm(char);
95 static int get_user_input(char*, size_t, char*);
96 static void print_col(Entry
*, size_t, size_t, size_t, int, int, char*);
97 static size_t scroll(size_t, size_t, size_t);
98 static int listdir(Pane
*, char*);
99 static void press(struct tb_event
*, Pane
*, Pane
*);
100 static void t_resize(Pane
*, Pane
*);
101 static int set_panes(Pane
*, Pane
*, int);
102 static void draw_frame(void);
103 static int start(void);
105 /* global variables */
106 static int parent_row
= 1; // FIX
108 /* function implementations */
110 print_tb(const char *str
, int x
, int y
, uint16_t fg
, uint16_t bg
)
112 while (*str
!= '\0') {
114 str
+= tb_utf8_char_to_unicode(&uni
, str
);
115 tb_change_cell(x
, y
, uni
, fg
, bg
);
121 printf_tb(int x
, int y
, uint16_t fg
, uint16_t bg
, const char *fmt
, ...)
126 (void)vsnprintf(buf
, sizeof(buf
), fmt
, vl
);
128 print_tb(buf
, x
, y
, fg
, bg
);
132 print_status(const char *fmt
, ...)
135 height
= tb_height();
140 vsnprintf(buf
, sizeof(buf
), fmt
, vl
);
143 print_tb(buf
, 2, height
-2, TB_DEFAULT
, status_b
);
148 print_xstatus(char c
, int x
)
152 height
= tb_height();
153 (void)tb_utf8_char_to_unicode(&uni
, &c
);
154 tb_change_cell(x
, height
-2, uni
, TB_DEFAULT
, status_b
);
158 print_error(const char *fmt
, ...)
162 height
= tb_height();
167 vsnprintf(buf
, sizeof(buf
), fmt
, vl
);
170 print_tb(buf
, width
-20, height
-2, 124, status_b
);
175 clear(int sx
, int ex
, int y
, uint16_t bg
)
177 /* clear line from to */
178 /* x = line number vertical */
179 /* y = column number horizontal */
181 for (i
= sx
; i
< ex
; i
++) {
182 tb_change_cell(i
, y
, 0x0000, TB_DEFAULT
, bg
);
192 height
= tb_height();
193 clear(1, width
-20, height
-2, status_b
);
201 height
= tb_height();
202 clear(width
-30, width
-1, height
-2, status_b
);
208 int i
, x
, ex
, y
, width
, height
;
210 height
= tb_height();
211 x
= 0, y
= 0, i
= 0, ex
= 0;
216 } else if (pane
== (width
/2) + 2) {
221 while (i
< height
-2) {
222 clear(x
, ex
, y
, TB_DEFAULT
);
227 for (y
= x
; y
< ex
; ++y
) {
228 tb_change_cell(y
, 0, u_hl
, frame_f
, frame_b
);
234 get_extentions(char *str
)
238 size_t counter
, len
, i
;
244 for (i
= len
-1; i
> 0; i
--) {
252 ext
= ecalloc(counter
+1, sizeof(char));
253 strncpy(ext
, &str
[len
-counter
], counter
);
258 get_full_path(char *first
, char *second
)
261 size_t full_path_len
;
263 full_path_len
= strlen(first
) + strlen(second
) + 2;
264 full_path
= ecalloc(full_path_len
, sizeof(char));
266 if (strcmp(first
, "/") == 0) {
267 (void)snprintf(full_path
, full_path_len
, "/%s", second
);
271 full_path
, full_path_len
, "%s/%s", first
, second
);
278 get_parent(char *dir
)
282 size_t counter
, len
, i
;
288 for (i
= len
-1; i
> 0; i
--) {
296 i
= len
- counter
- 1;
299 parent
= ecalloc(i
+1, sizeof(char));
300 strncpy(parent
, dir
, i
);
306 get_file_info(Entry
*cursor
)
308 char *size
, *result
, *ur
, *gr
, *td
, *perm
;
309 size_t size_len
= (size_t)9;
310 size_t perm_len
= (size_t)11;
311 size_t ur_len
= (size_t)32;
312 size_t gr_len
= (size_t)32;
313 size_t td_len
= (size_t)14;
314 size_t result_chars
= size_len
+ perm_len
+ ur_len
+ gr_len
+ td_len
;
315 result
= ecalloc(result_chars
, sizeof(char));
317 size
= get_file_size(cursor
->size
);
318 td
= get_file_date_time(cursor
->td
);
319 perm
= get_file_perm(cursor
->mode
);
321 strncpy(result
, perm
, perm_len
);
323 strncat(result
, size
, size_len
);
327 ur
= get_file_userowner(cursor
->user
, ur_len
);
328 gr
= get_file_groupowner(cursor
->group
, gr_len
);
329 strncat(result
, ur
, ur_len
);
331 strncat(result
, gr
, gr_len
);
337 strncat(result
, td
, td_len
);
347 get_file_size(off_t size
)
349 /* need to be freed */
355 Rsize
= ecalloc(10, sizeof(char));
358 while (lsize
>= 1000)
364 float_to_string(lsize
, Rsize
);
389 get_file_date_time(time_t status
)
395 result_len
= (size_t)14;
396 result
= ecalloc(result_len
, sizeof(char));
397 localtime_r(&status
, <
);
399 if (strftime(result
, result_len
, dt_fmt
, <
) != sizeof(dt_fmt
)-1) {
408 get_file_userowner(uid_t status
, size_t len
)
413 result
= ecalloc(len
, sizeof(char));
414 pw
= getpwuid(status
);
416 (void)snprintf(result
, len
-1, "%d", (int)status
);
418 strncpy(result
, pw
->pw_name
, len
-1);
424 get_file_groupowner(gid_t status
, size_t len
)
429 result
= ecalloc(len
, sizeof(char));
430 gr
= getgrgid(status
);
432 (void)snprintf(result
, len
-1, "%d", (int)status
);
434 strncpy(result
, gr
->gr_name
, len
-1);
440 get_file_perm(mode_t mode
)
445 const char chars
[] = "rwxrwxrwx";
446 buf
= ecalloc(11, sizeof(char));
450 else if(S_ISREG(mode
))
452 else if(S_ISLNK(mode
))
454 else if(S_ISBLK(mode
))
456 else if(S_ISCHR(mode
))
458 else if(S_ISFIFO(mode
))
460 else if(S_ISSOCK(mode
))
465 for (i
= 1; i
< 10; i
++) {
466 buf
[i
] = (mode
& (1 << (9-i
))) ? chars
[i
-1] : '-';
474 create_new_dir(char *cwd
, char *user_input
)
477 path
= ecalloc(strlen(cwd
)+strlen(user_input
)+2, sizeof(char));
480 strcat(path
, user_input
);
482 if(mkdir(path
, new_dir_perm
) < 0) {
492 create_new_file(char *cwd
, char *user_input
)
495 path
= ecalloc(strlen(cwd
)+strlen(user_input
)+2, sizeof(char));
498 strcat(path
, user_input
);
501 file_ptr
= fopen(path
, "w");
504 if (file_ptr
!= NULL
) {
505 (void)fclose(file_ptr
);
514 delete_ent(char *fullpath
)
519 if (lstat(fullpath
, &status
) < 0)
522 mode
= status
.st_mode
;
524 return delete_dir(fullpath
, AskDel
);
526 return delete_file(fullpath
);
532 delete_dir(char *fullpath
, int delchoice
)
534 if (delchoice
== AskDel
) {
536 confirmation
= ecalloc((size_t)2, sizeof(char));
538 confirmation
, 2,"delete directory (Y) ?") < 0) ||
539 (strcmp(confirmation
, "Y") != 0)) {
541 return 1; /* canceled by user or wrong confirmation */
546 if (rmdir(fullpath
) == 0)
547 return 0; /* empty directory */
552 struct dirent
*entry
;
555 dir
= opendir(fullpath
);
560 while ((entry
= readdir(dir
)) != 0) {
561 if ((strcmp(entry
->d_name
, ".") == 0 ||
562 strcmp(entry
->d_name
, "..") == 0))
565 ent_full
= get_full_path(fullpath
, entry
->d_name
);
566 if (lstat(ent_full
, &status
) == 0) {
567 mode
= status
.st_mode
;
569 if (delete_dir(ent_full
, DAskDel
) < 0) {
573 } else if (S_ISREG(mode
)) {
574 if (unlink(ent_full
) < 0) {
583 print_status("gotit");
584 if (closedir(dir
) < 0)
587 return rmdir(fullpath
); /* directory after delete all entries */
591 delete_file(char *fullpath
)
594 confirmation
= ecalloc((size_t)2, sizeof(char));
596 if ((get_user_input(confirmation
, 2, "delete file (Y) ?") < 0) ||
597 (strcmp(confirmation
, "Y") != 0)) {
599 return 1; /* canceled by user or wrong confirmation */
603 return unlink(fullpath
);
607 check_dir(char *path
)
613 if (errno
== ENOTDIR
) {
620 if (closedir(dir
) < 0)
627 chech_execf(mode_t mode
)
630 return ((S_IXUSR
| S_IXGRP
| S_IXOTH
) & mode
);
635 open_files(char *filename
)
638 /* open editor in other window */
640 char *editor
, *file_ex
, *software
, *term
;
645 editor
= getenv("EDITOR");
646 term
= getenv("TERM");
647 file_ex
= get_extentions(filename
);
650 /* find software in rules */
651 for (c
= 0; c
< LEN(rules
); c
++) {
652 for (d
= 0; d
< rules
[c
].len
; d
++){
653 if (strcmp(rules
[c
].ext
[d
], file_ex
) == 0) {
654 software
= rules
[c
].soft
;
659 /* default softwares */
661 term
= "xterm-256color";
664 if (software
== NULL
)
668 char *filex
[] = {software
, filename
, NULL
};
676 (void)execvp(filex
[0], filex
);
679 while ((r
= waitpid(pid
, &status
, 0)) == -1 && errno
== EINTR
)
683 if ((WIFEXITED(status
) != 0) && (WEXITSTATUS(status
) != 0))
691 sort_name(const void *const A
, const void *const B
)
694 mode_t data1
= (*(Entry
*) A
).mode
;
695 mode_t data2
= (*(Entry
*) B
).mode
;
699 } else if (data1
== data2
) {
700 result
= strcmp((*(Entry
*) A
).name
,(*(Entry
*) B
).name
);
708 float_to_string(float f
, char *r
)
710 int length
, length2
, i
, number
, position
, tenth
; /* length is size of decimal part, length2 is size of tenth part */
713 f
= (float)(int)(f
* 10) / 10;
720 /* Calculate length2 tenth part */
721 while ((number2
- (float)number
) != 0.0 && !((number2
- (float)number
) < 0.0))
724 number2
= f
* (float)tenth
;
725 number
= (int)number2
;
730 /* Calculate length decimal part */
731 for (length
= (f
> 1.0) ? 0 : 1; f
> 1.0; length
++)
735 length
= length
+ 1 + length2
;
736 number
= (int)number2
;
740 for (i
= length
; i
>= 0; i
--)
744 else if (i
== (position
))
748 r
[i
] = (char)(number
% 10) + '0';
756 for (i
= length
; i
>= 0; i
--)
762 r
[i
] = (char)(number
% 10) + '0';
774 for (i
= 0; i
< LEN(bmarks
); i
++) {
775 if (event
== bmarks
[i
].key
) {
776 if (check_dir(bmarks
[i
].path
) != 0) {
777 print_error("%s", strerror(errno
));
787 get_user_input(char *out
, size_t sout
, char *prompt
)
789 int height
= tb_height();
797 startat
= strlen(prompt
) + 3;
798 print_status("%s:", prompt
);
799 tb_set_cursor(startat
+ 1, height
-2);
802 while (tb_poll_event(&fev
) != 0) {
805 if (fev
.key
== TB_KEY_ESC
) {
806 tb_set_cursor(-1, -1);
811 if (fev
.key
== TB_KEY_BACKSPACE
||
812 fev
.key
== TB_KEY_BACKSPACE2
) {
813 if (BETWEEN(counter
, 2, sout
)) {
817 print_xstatus(empty
, startat
+ counter
);
819 startat
+ counter
, height
- 2);
822 } else if (fev
.key
== TB_KEY_ENTER
) {
823 tb_set_cursor(-1, -1);
824 out
[counter
-1] = '\0';
828 if (counter
< sout
) {
829 print_xstatus((char)fev
.ch
, startat
+counter
);
830 out
[x
] = (char)fev
.ch
;
831 tb_set_cursor(startat
+ counter
+ 1,height
-2);
850 print_col(Entry
*entry
, size_t hdir
, size_t x
, size_t y
, int dyn_y
, int width
, char *filter
)
857 if (S_ISDIR(entry
->mode
)) {
860 } else if (S_ISLNK(entry
->mode
)) {
861 realpath(entry
->full
, buf
);
862 strcat(entry
->name
, " -> ");
863 strncat(entry
->name
, buf
, MAX_N
- strlen(entry
->name
)-1);
868 /* highlight executable files */
869 if (chech_execf(entry
->mode
))
872 /* highlighted (cursor) */
873 if (y
+ dyn_y
== hdir
) {
874 bg
= bg
| TB_REVERSE
;
875 fg
= fg
| TB_REVERSE
| TB_BOLD
;
878 /* highlight found filter */
879 if (filter
!= NULL
) {
880 if (strstr(entry
->name
, filter
) != NULL
) {
882 fg
= search_f
| TB_BOLD
;
886 /* print each element in directory */
887 printf_tb((int)x
, (int)y
, fg
, bg
, "%*.*s", ~width
, width
, entry
->name
);
892 scroll(size_t height
, size_t dirc
, size_t hdir
)
894 size_t result
, limit
;
897 limit
= (height
-1) / 2;
898 if (dirc
> height
- 1) {
901 } else if (hdir
> dirc
- limit
) {
902 result
= dirc
- height
+ 1;
904 result
= hdir
- limit
;
911 listdir(Pane
*cpane
, char *filter
)
914 struct dirent
*entry
;
920 size_t y
, i
, height
, dyn_max
, dyn_y
, start_from
;
922 height
= (size_t)tb_height() - 2;
923 width
= (tb_width() / 2) - 4;
924 cpane
->dirc
= - 2; /* dont't count . .. */
927 dir
= opendir(cpane
->dirn
);
931 /* get content sum */
932 while ((entry
= readdir(dir
)) != 0) {
936 /* empty directory */
937 if (cpane
->dirc
== 0) {
938 if (closedir(dir
) < 0)
941 /* print current directory title */
942 printf_tb(cpane
->dirx
, 0, cpane
->dir_fg
| TB_BOLD
,
943 cpane
->dir_bg
, " %.*s ", width
, cpane
->dirn
);
947 rewinddir(dir
); /* reset position */
949 /* create array of entries */
951 list
= ecalloc(cpane
->dirc
, sizeof(Entry
));
952 while ((entry
= readdir(dir
)) != 0) {
953 if ((strcmp(entry
->d_name
, ".") == 0 ||
954 strcmp(entry
->d_name
, "..") == 0))
957 strcpy(list
[i
].name
, entry
->d_name
);
958 fullpath
= get_full_path(cpane
->dirn
, entry
->d_name
);
959 strcpy(list
[i
].full
, fullpath
);
961 if (lstat(fullpath
, &status
) == 0) {
962 list
[i
].size
= status
.st_size
;
963 list
[i
].mode
= status
.st_mode
;
964 list
[i
].group
= status
.st_gid
;
965 list
[i
].user
= status
.st_uid
;
966 list
[i
].td
= status
.st_mtime
;
974 qsort(list
, cpane
->dirc
, sizeof(Entry
), sort_name
);
979 start_from
= scroll(height
, cpane
->dirc
, cpane
->hdir
);
981 dyn_max
= MIN(cpane
->dirc
, (height
- 1) + start_from
);
983 /* get full path of cursor */
984 fullpath
= get_full_path(cpane
->dirn
,
985 list
[cpane
->hdir
-1].name
);
986 strncpy(cpane
->high_dir
, fullpath
, (size_t)MAX_P
);
989 /* print each entry in directory */
990 while (start_from
< dyn_max
) {
991 print_col(&list
[start_from
], cpane
->hdir
,
992 (size_t)cpane
->dirx
, y
, (int)dyn_y
, width
, filter
);
997 fileinfo
= get_file_info(&list
[cpane
->hdir
-1]);
999 /* print info in statusbar */
1000 print_status("%lu/%lu %s",
1005 /* print current directory title */
1006 printf_tb(cpane
->dirx
, 0, cpane
->dir_fg
| TB_BOLD
, cpane
->dir_bg
,
1007 " %.*s ", width
, cpane
->dirn
);
1012 if (closedir(dir
) < 0)
1015 // print_error("mem (%d)", get_memory_usage());
1021 press(struct tb_event
*ev
, Pane
*cpane
, Pane
*opane
)
1027 if (ev
->ch
== 'j') {
1028 if (cpane
->hdir
< cpane
->dirc
) {
1030 (void)listdir(cpane
, NULL
);
1032 } else if (ev
->ch
== 'k') {
1033 if (cpane
->hdir
> 1) {
1035 (void)listdir(cpane
, NULL
);
1037 } else if (ev
->ch
== 'h') {
1038 parent
= get_parent(cpane
->dirn
);
1039 if (check_dir(parent
) < 0) { /* failed to open directory */
1040 print_error("%s", strerror(errno
));
1042 strcpy(cpane
->dirn
, parent
);
1043 clear_pane(cpane
->dirx
);
1044 cpane
->hdir
= (size_t)parent_row
;
1045 (void)listdir(cpane
, NULL
);
1049 } else if (ev
->ch
== 'l') {
1050 switch (check_dir(cpane
->high_dir
)) {
1052 strcpy(cpane
->dirn
, cpane
->high_dir
);
1053 clear_pane(cpane
->dirx
);
1054 parent_row
= (int)cpane
->hdir
;
1056 (void)listdir(cpane
, NULL
);
1059 /* is not a directory open file */
1060 if (open_files(cpane
->high_dir
) < 0) {
1061 print_error("procces failed");
1066 if (cpane
->dirx
== 2) /* if current left pane */
1067 t_resize(cpane
, opane
);
1069 t_resize(opane
, cpane
);
1072 /* failed to open directory */
1073 print_error("%s", strerror(errno
));
1075 } else if (ev
->ch
== 'g') {
1077 (void)listdir(cpane
, NULL
);
1078 } else if (ev
->ch
== 'G') {
1079 cpane
->hdir
= cpane
->dirc
;
1080 (void)listdir(cpane
, NULL
);
1081 } else if (ev
->ch
== 'M') {
1082 cpane
->hdir
= (cpane
->dirc
/2);
1083 (void)listdir(cpane
, NULL
);
1084 } else if (ev
->key
== TB_KEY_CTRL_U
) {
1085 if (cpane
->hdir
> move_ud
)
1086 cpane
->hdir
= cpane
->hdir
- move_ud
;
1089 (void)listdir(cpane
, NULL
);
1090 } else if (ev
->key
== TB_KEY_CTRL_D
) {
1091 if (cpane
->hdir
< cpane
->dirc
- move_ud
)
1092 cpane
->hdir
= cpane
->hdir
+ move_ud
;
1094 cpane
->hdir
= cpane
->dirc
;
1095 (void)listdir(cpane
, NULL
);
1096 } else if (ev
->ch
== 'n') {
1098 user_input
= ecalloc(MAX_USRI
, sizeof(char));
1099 if (get_user_input(user_input
, MAX_USRI
, "new file") < 0) {
1103 if (create_new_file(cpane
->dirn
, user_input
) < 0)
1104 print_error("%s", strerror(errno
));
1106 listdir(cpane
, NULL
);
1108 } else if (ev
->ch
== 'N') {
1110 user_input
= ecalloc(MAX_USRI
, sizeof(char));
1111 if (get_user_input(user_input
, MAX_USRI
, "new directory") < 0) {
1115 if (create_new_dir(cpane
->dirn
, user_input
) < 0)
1116 print_error("%s", strerror(errno
));
1118 listdir(cpane
, NULL
);
1121 } else if (ev
->ch
== 'D') {
1122 switch (delete_ent(cpane
->high_dir
)) {
1124 print_error("%s", strerror(errno
));
1127 clear_pane(cpane
->dirx
);
1128 if (cpane
->hdir
== cpane
->dirc
) /* last entry */
1130 listdir(cpane
, NULL
);
1133 } else if (ev
->ch
== '/') {
1135 user_input
= ecalloc(MAX_USRI
, sizeof(char));
1136 if (get_user_input(user_input
, MAX_USRI
, "filter") < 0) {
1140 print_error("out -> %s", user_input
);
1141 listdir(cpane
, user_input
);
1145 b
= (int)findbm((char)ev
->ch
);
1149 strcpy(cpane
->dirn
, bmarks
[b
].path
);
1150 clear_pane(cpane
->dirx
);
1152 (void)listdir(cpane
, NULL
);
1158 t_resize(Pane
*cpane
, Pane
*opane
)
1162 (void)set_panes(cpane
, opane
, 1);
1163 (void)listdir(cpane
, NULL
);
1164 (void)listdir(opane
, NULL
);
1170 set_panes(Pane
*pane_l
, Pane
*pane_r
, int resize
)
1176 if ((getcwd(cwd
, sizeof(cwd
)) == NULL
))
1179 home
= getenv("HOME");
1186 pane_l
->dir_fg
= pane_l_f
;
1187 pane_l
->dir_bg
= pane_l_b
;
1189 strcpy(pane_l
->dirn
, cwd
);
1193 pane_r
->dirx
= (width
/ 2) + 2;
1194 pane_r
->dir_fg
= pane_r_f
;
1195 pane_r
->dir_bg
= pane_r_b
;
1198 strcpy(pane_r
->dirn
, home
);
1208 int height
, width
, i
;
1211 height
= tb_height();
1213 /* 2 horizontal lines */
1214 for (i
= 1; i
< width
-1 ; ++i
) {
1215 tb_change_cell(i
, 0, u_hl
, frame_f
, frame_b
);
1216 tb_change_cell(i
, height
-1, u_hl
, frame_f
, frame_b
);
1219 /* 3 vertical lines */
1220 for (i
= 1; i
< height
-1 ; ++i
) {
1221 tb_change_cell(0, i
, u_vl
, frame_f
, frame_b
);
1222 tb_change_cell((width
-1)/2, i
-1, u_vl
, frame_f
, frame_b
);
1223 tb_change_cell(width
-1, i
, u_vl
, frame_f
, frame_b
);
1227 tb_change_cell(0, 0, u_cnw
, frame_f
, frame_b
);
1228 tb_change_cell(width
-1, 0, u_cne
, frame_f
, frame_b
);
1229 tb_change_cell(0, height
-1, u_csw
, frame_f
, frame_b
);
1230 tb_change_cell(width
-1, height
-1, u_cse
, frame_f
, frame_b
);
1232 /* 2 middel top and bottom */
1233 tb_change_cell((width
-1)/2, 0, u_mn
, frame_f
, frame_b
);
1240 int init_height
, init_width
;
1242 Pane pane_r
, pane_l
;
1243 int current_pane
= 0;
1248 init_width
= tb_width();
1249 init_height
= tb_height();
1251 if (tb_select_output_mode(TB_OUTPUT_256
) != TB_OUTPUT_256
)
1252 (void)tb_select_output_mode(TB_OUTPUT_NORMAL
);
1256 (void)set_panes(&pane_l
, &pane_r
, 0);
1257 (void)listdir(&pane_r
, NULL
);
1258 (void)listdir(&pane_l
, NULL
);
1261 while (tb_poll_event(&ev
) != 0) {
1268 } else if (ev
.key
== TB_KEY_SPACE
) {
1269 current_pane
= !current_pane
;
1272 if (current_pane
== 0) {
1273 press(&ev
, &pane_l
, &pane_r
);
1275 } else if (current_pane
== 1) {
1276 press(&ev
, &pane_r
, &pane_l
);
1282 case TB_EVENT_RESIZE
:
1283 t_resize(&pane_l
, &pane_r
);
1296 main(int argc
, char *argv
[])
1299 if (pledge("stdio tty rpath proc exec", NULL
) == -1)
1301 #endif /* __OpenBSD__ */
1304 die("start failed");
1306 argc
== 2 && strlen(argv
[1]) == (size_t)2 &&
1307 strcmp("-v", argv
[1]) == 0) {
1310 die("usage: sfm [-v]");