void subScreenRender(void) { int i, j; /* Render all screens */ for(i = 0; i < subtle->screens->ndata; i++) { SubScreen *s = SCREEN(subtle->screens->data[i]); Window panel = s->panel1; ScreenClear(s, subtle->styles.subtle.top); /* Render panel items */ for(j = 0; s->panels && j < s->panels->ndata; j++) { SubPanel *p = PANEL(s->panels->data[j]); if(p->flags & SUB_PANEL_HIDDEN) continue; if(panel != s->panel2 && p->flags & SUB_PANEL_BOTTOM) { ScreenCopy(s, panel); ScreenClear(s, subtle->styles.subtle.bottom); panel = s->panel2; } subPanelRender(p, s->drawable); } ScreenCopy(s, panel); } XSync(subtle->dpy, False); ///< Sync before going on } /* }}} */
void quick_view_cmd (void) { if (PANEL (get_panel_widget (MENU_PANEL_IDX)) == current_panel) change_panel (); set_display_type (MENU_PANEL_IDX, view_quick); }
SubPanel * subPanelNew(int type) { SubPanel *p = NULL; /* Create new panel */ p = PANEL(subSharedMemoryAlloc(1, sizeof(SubPanel))); p->flags = (SUB_TYPE_PANEL|type); /* Handle panel item type */ switch(p->flags & (SUB_PANEL_ICON|SUB_PANEL_SUBLET|SUB_PANEL_VIEWS)) { case SUB_PANEL_ICON: /* {{{ */ p->icon = ICON(subSharedMemoryAlloc(1, sizeof(SubIcon))); break; /* }}} */ case SUB_PANEL_SUBLET: /* {{{ */ p->sublet = SUBLET(subSharedMemoryAlloc(1, sizeof(SubSublet))); /* Sublet specific */ p->sublet->time = subSubtleTime(); p->sublet->text = subSharedTextNew(); p->sublet->style = -1; break; /* }}} */ case SUB_PANEL_VIEWS: /* {{{ */ p->flags |= SUB_PANEL_DOWN; break; /* }}} */ } subSharedLogDebugSubtle("new=panel, type=%s\n", SUB_PANEL_VIEWS == type ? "views" : "title"); return p; } /* }}} */
static void panel_do_cols (int idx) { if (get_display_type (idx) == view_listing) set_panel_formats (PANEL (panels[idx].widget)); else panel_update_cols (panels[idx].widget, frame_half); }
void toggle_listing_cmd (void) { int current; WPanel *p; current = get_current_index (); p = PANEL (get_panel_widget (current)); set_basic_panel_listing_to (current, (p->list_type + 1) % LIST_TYPES); }
char * get_panel_dir_for (const WPanel * widget) { int i; for (i = 0; i < MAX_VIEWS; i++) if (PANEL (get_panel_widget (i)) == widget) break; if (i >= MAX_VIEWS) return g_strdup ("."); if (get_display_type (i) == view_listing) { vfs_path_t *cwd_vpath; cwd_vpath = PANEL (get_panel_widget (i))->cwd_vpath; return g_strdup (vfs_path_as_str (cwd_vpath)); } return g_strdup (panels[i].last_saved_dir); }
void save_panel_dir (int idx) { panel_view_mode_t type = get_display_type (idx); Widget *widget = get_panel_widget (idx); if ((type == view_listing) && (widget != NULL)) { WPanel *w = PANEL (widget); g_free (panels[idx].last_saved_dir); /* last path no needed */ /* Because path can be nonlocal */ panels[idx].last_saved_dir = g_strdup (vfs_path_as_str (w->cwd_vpath)); } }
static gboolean set_basic_panel_listing_to (int panel_index, int listing_mode) { WPanel *p; gboolean ok; p = PANEL (get_panel_widget (panel_index)); switch_to_listing (panel_index); p->list_type = listing_mode; ok = set_panel_formats (p) == 0; if (ok) do_refresh (); return ok; }
static void switch_to_listing (int panel_index) { if (get_display_type (panel_index) != view_listing) set_display_type (panel_index, view_listing); else { WPanel *p; p = PANEL (get_panel_widget (panel_index)); if (p->is_panelized) { p->is_panelized = FALSE; panel_reload (p); } } }
void subScreenRender(void) { int i, j; /* Render all screens */ for(i = 0; i < subtle->screens->ndata; i++) { SubScreen *s = SCREEN(subtle->screens->data[i]); Window panel = s->panel1; ScreenClear(s, subtle->styles.subtle.top); /* Render panel items */ for(j = 0; s->panels && j < s->panels->ndata; j++) { SubPanel *p = PANEL(s->panels->data[j]); if(p->flags & SUB_PANEL_HIDDEN) continue; if(panel != s->panel2 && p->flags & SUB_PANEL_BOTTOM) { XCopyArea(subtle->dpy, s->drawable, panel, subtle->gcs.draw, 0, 0, s->base.width, subtle->ph, 0, 0); ScreenClear(s, subtle->styles.subtle.bottom); panel = s->panel2; } subPanelRender(p, s->drawable); } XCopyArea(subtle->dpy, s->drawable, panel, subtle->gcs.draw, 0, 0, s->base.width, subtle->ph, 0, 0); } XSync(subtle->dpy, False); ///< Sync before going on subSubtleLogDebugSubtle("Render\n"); } /* }}} */
void subPanelPublish(void) { int i = 0, j = 0, idx = 0; char **names = NULL; /* Alloc space */ names = (char **)subSharedMemoryAlloc(subtle->sublets->ndata, sizeof(char *)); /* Find sublet in panels */ for(i = 0; i < subtle->screens->ndata; i++) { SubScreen *s = SCREEN(subtle->screens->data[i]); if(s->panels) { for(j = 0; j < s->panels->ndata; j++) { SubPanel *p = PANEL(s->panels->data[j]); /* Include sublets, exclude shallow copies */ if(p->flags & SUB_PANEL_SUBLET && !(p->flags & SUB_PANEL_COPY)) names[idx++] = p->sublet->name; } } } /* EWMH: Sublet list and windows */ subSharedPropertySetStrings(subtle->dpy, ROOT, subEwmhGet(SUB_EWMH_SUBTLE_SUBLET_LIST), names, subtle->sublets->ndata); subSharedLogDebugSubtle("publish=panel, n=%d\n", subtle->sublets->ndata); XSync(subtle->dpy, False); ///< Sync all changes free(names); } /* }}} */
void subScreenUpdate(void) { int i; /* Update screens */ for(i = 0; i < subtle->screens->ndata; i++) { SubScreen *s = SCREEN(subtle->screens->data[i]); SubPanel *p = NULL; int j, npanel = 0, center = False, offset = 0; int x[4] = { 0 }, nspacer[4] = { 0 }; ///< Waste ints but it's easier for the algo int sw[4] = { 0 }, fix[4] = { 0 }, width[4] = { 0 }, spacer[4] = { 0 }; /* Pass 1: Collect width for spacer sizes */ for(j = 0; s->panels && j < s->panels->ndata; j++) { p = PANEL(s->panels->data[j]); subPanelUpdate(p); /* Check flags */ if(p->flags & SUB_PANEL_HIDDEN) continue; if(0 == npanel && p->flags & SUB_PANEL_BOTTOM) { npanel = 1; center = False; } if(p->flags & SUB_PANEL_CENTER) center = !center; /* Offset selects panel variables for either center or not */ offset = center ? npanel + 2 : npanel; if(p->flags & SUB_PANEL_SPACER1) spacer[offset]++; if(p->flags & SUB_PANEL_SPACER2) spacer[offset]++; if(p->flags & SUB_PANEL_SEPARATOR1) width[offset] += subtle->separator.width; if(p->flags & SUB_PANEL_SEPARATOR2) width[offset] += subtle->separator.width; width[offset] += p->width; } /* Calculate spacer and fix sizes */ for(j = 0; j < 4; j++) { if(0 < spacer[j]) { sw[j] = (s->base.width - width[j]) / spacer[j]; fix[j] = s->base.width - (width[j] + spacer[j] * sw[j]); } } /* Pass 2: Move and resize windows */ for(j = 0, npanel = 0, center = False; s->panels && j < s->panels->ndata; j++) { p = PANEL(s->panels->data[j]); /* Check flags */ if(p->flags & SUB_PANEL_HIDDEN) continue; if(0 == npanel && p->flags & SUB_PANEL_BOTTOM) { /* Reset for new panel */ npanel = 1; nspacer[0] = 0; nspacer[2] = 0; x[0] = 0; x[2] = 0; center = False; } if(p->flags & SUB_PANEL_CENTER) center = !center; /* Offset selects panel variables for either center or not */ offset = center ? npanel + 2 : npanel; /* Set start position of centered panel items */ if(center && 0 == x[offset]) x[offset] = (s->base.width - width[offset]) / 2; /* Add separator before panel item */ if(p->flags & SUB_PANEL_SEPARATOR1) x[offset] += subtle->separator.width; /* Add spacer before item */ if(p->flags & SUB_PANEL_SPACER1) { x[offset] += sw[offset]; /* Increase last spacer size by rounding fix */ if(++nspacer[offset] == spacer[offset]) x[offset] += fix[offset]; } /* Set panel position */ if(p->flags & SUB_PANEL_TRAY) XMoveWindow(subtle->dpy, subtle->windows.tray, x[offset], 0); p->x = x[offset]; /* Add separator after panel item */ if(p->flags & SUB_PANEL_SEPARATOR2) x[offset] += subtle->separator.width; /* Add spacer after item */ if(p->flags & SUB_PANEL_SPACER2) { x[offset] += sw[offset]; /* Increase last spacer size by rounding fix */ if(++nspacer[offset] == spacer[offset]) x[offset] += fix[offset]; } x[offset] += p->width; } } } /* }}} */
void set_display_type (int num, panel_view_mode_t type) { int x = 0, y = 0, cols = 0, lines = 0; unsigned int the_other = 0; /* Index to the other panel */ const char *file_name = NULL; /* For Quick view */ Widget *new_widget = NULL, *old_widget = NULL; panel_view_mode_t old_type = view_listing; WPanel *the_other_panel = NULL; if (num >= MAX_VIEWS) { fprintf (stderr, "Cannot allocate more that %d views\n", MAX_VIEWS); abort (); } /* Check that we will have a WPanel * at least */ if (type != view_listing) { the_other = num == 0 ? 1 : 0; if (panels[the_other].type != view_listing) return; } /* Get rid of it */ if (panels[num].widget != NULL) { Widget *w = panels[num].widget; WPanel *panel = PANEL (w); x = w->x; y = w->y; cols = w->cols; lines = w->lines; old_widget = w; old_type = panels[num].type; if (old_type == view_listing && panel->frame_size == frame_full && type != view_listing) { if (panels_layout.horizontal_split) { cols = COLS; x = 0; } else { cols = COLS - panels_layout.left_panel_size; if (num == 1) x = panels_layout.left_panel_size; } } } /* Restoring saved path from panels.ini for nonlist panel */ /* when it's first creation (for example view_info) */ if (old_widget == NULL && type != view_listing) { char *panel_dir; panel_dir = _vfs_get_cwd (); panels[num].last_saved_dir = g_strdup (panel_dir); g_free (panel_dir); } switch (type) { case view_nothing: case view_listing: new_widget = restore_into_right_dir_panel (num, old_widget); widget_set_size (new_widget, y, x, lines, cols); break; case view_info: new_widget = WIDGET (info_new (y, x, lines, cols)); break; case view_tree: new_widget = WIDGET (tree_new (y, x, lines, cols, TRUE)); break; case view_quick: new_widget = WIDGET (mcview_new (y, x, lines, cols, TRUE)); the_other_panel = PANEL (panels[the_other].widget); if (the_other_panel != NULL) file_name = the_other_panel->dir.list[the_other_panel->selected].fname; else file_name = ""; mcview_load ((struct mcview_struct *) new_widget, 0, file_name, 0, 0, 0); break; default: break; } if (type != view_listing) /* Must save dir, for restoring after change type to */ /* view_listing */ save_panel_dir (num); panels[num].type = type; panels[num].widget = new_widget; /* We use replace to keep the circular list of the dialog in the */ /* same state. Maybe we could just kill it and then replace it */ if ((midnight_dlg != NULL) && (old_widget != NULL)) { if (old_type == view_listing) { /* save and write directory history of panel * ... and other histories of midnight_dlg */ dlg_save_history (midnight_dlg); } widget_replace (old_widget, new_widget); } if (type == view_listing) { WPanel *panel = PANEL (new_widget); /* if existing panel changed type to view_listing, then load history */ if (old_widget != NULL) { ev_history_load_save_t event_data = { NULL, new_widget }; mc_event_raise (midnight_dlg->event_group, MCEVENT_HISTORY_LOAD, &event_data); } if (num == 0) left_panel = panel; else right_panel = panel; /* forced update format after set new sizes */ set_panel_formats (panel); } if (type == view_tree) the_tree = (WTree *) new_widget; /* Prevent current_panel's value from becoming invalid. * It's just a quick hack to prevent segfaults. Comment out and * try following: * - select left panel * - invoke menue left/tree * - as long as you stay in the left panel almost everything that uses * current_panel causes segfault, e.g. C-Enter, C-x c, ... */ if ((type != view_listing) && (current_panel == PANEL (old_widget))) current_panel = num == 0 ? right_panel : left_panel; g_free (old_widget); }
WPanel * get_other_panel (void) { return PANEL (get_panel_widget (get_other_index ())); }
void swap_panels (void) { WPanel *panel1, *panel2; Widget *tmp_widget; panel1 = PANEL (panels[0].widget); panel2 = PANEL (panels[1].widget); if (panels[0].type == view_listing && panels[1].type == view_listing && !mc_config_get_bool (mc_main_config, CONFIG_PANELS_SECTION, "simple_swap", FALSE)) { WPanel panel; #define panelswap(x) panel.x = panel1->x; panel1->x = panel2->x; panel2->x = panel.x; #define panelswapstr(e) strcpy (panel.e, panel1->e); \ strcpy (panel1->e, panel2->e); \ strcpy (panel2->e, panel.e); /* Change content and related stuff */ panelswap (dir); panelswap (active); panelswap (cwd_vpath); panelswap (lwd_vpath); panelswap (marked); panelswap (dirs_marked); panelswap (total); panelswap (top_file); panelswap (selected); panelswap (is_panelized); panelswap (dir_stat); #undef panelswapstr #undef panelswap panel1->searching = FALSE; panel2->searching = FALSE; if (current_panel == panel1) current_panel = panel2; else current_panel = panel1; /* if sort options are different -> resort panels */ if (memcmp (&panel1->sort_info, &panel2->sort_info, sizeof (dir_sort_options_t)) != 0) { panel_re_sort (other_panel); panel_re_sort (current_panel); } if (widget_is_active (panels[0].widget)) dlg_select_widget (panels[1].widget); else if (widget_is_active (panels[1].widget)) dlg_select_widget (panels[0].widget); } else { WPanel *tmp_panel; int x, y, cols, lines; int tmp_type; tmp_panel = right_panel; right_panel = left_panel; left_panel = tmp_panel; if (panels[0].type == view_listing) { if (strcmp (panel1->panel_name, get_nth_panel_name (0)) == 0) { g_free (panel1->panel_name); panel1->panel_name = g_strdup (get_nth_panel_name (1)); } } if (panels[1].type == view_listing) { if (strcmp (panel2->panel_name, get_nth_panel_name (1)) == 0) { g_free (panel2->panel_name); panel2->panel_name = g_strdup (get_nth_panel_name (0)); } } x = panels[0].widget->x; y = panels[0].widget->y; cols = panels[0].widget->cols; lines = panels[0].widget->lines; panels[0].widget->x = panels[1].widget->x; panels[0].widget->y = panels[1].widget->y; panels[0].widget->cols = panels[1].widget->cols; panels[0].widget->lines = panels[1].widget->lines; panels[1].widget->x = x; panels[1].widget->y = y; panels[1].widget->cols = cols; panels[1].widget->lines = lines; tmp_widget = panels[0].widget; panels[0].widget = panels[1].widget; panels[1].widget = tmp_widget; tmp_type = panels[0].type; panels[0].type = panels[1].type; panels[1].type = tmp_type; /* force update formats because of possible changed sizes */ if (panels[0].type == view_listing) set_panel_formats (PANEL (panels[0].widget)); if (panels[1].type == view_listing) set_panel_formats (PANEL (panels[1].widget)); } }
void subPanelAction(SubArray *panels, int type, int x, int y, int button, int bottom) { int i; /* FIXME: In order to find the correct panel item we * need to check all of them in a O(n) fashion and * check if they belong to the top or bottom panel. * Adding some kind of map for the x values would * be nice. */ /* Check panel items */ for(i = 0; i < panels->ndata; i++) { SubPanel *p = PANEL(panels->data[i]); /* Check if x is in panel rect */ if(p->flags & type && x >= p->x && x <= p->x + p->width) { /* Check if action is for bottom panel */ if((bottom && !(p->flags & SUB_PANEL_BOTTOM)) || (!bottom && p->flags & SUB_PANEL_BOTTOM)) continue; /* Handle panel item type */ switch(p->flags & (SUB_PANEL_SUBLET|SUB_PANEL_VIEWS)) { case SUB_PANEL_SUBLET: /* {{{ */ /* Handle action type */ switch(type) { case SUB_PANEL_OUT: subRubyCall(SUB_CALL_OUT, p->sublet->instance, NULL); break; case SUB_PANEL_OVER: subRubyCall(SUB_CALL_OVER, p->sublet->instance, NULL); break; case SUB_PANEL_DOWN: { int args[3] = { x - p->x, y, button }; subRubyCall(SUB_CALL_DOWN, p->sublet->instance, (void *)&args); } break; } subScreenUpdate(); subScreenRender(); break; /* }}} */ case SUB_PANEL_VIEWS: /* {{{ */ { int j, vx = p->x; for(j = 0; j < subtle->views->ndata; j++) { SubView *v = VIEW(subtle->views->data[j]); SubStyle *s = PanelViewStyle(v, (p->screen->vid == i)); int swidth = v->width + STYLE_WIDTH((*s)); ///< Get width with style /* Check dynamic views */ if(v->flags & SUB_VIEW_DYNAMIC && !(subtle->client_tags & v->tags)) continue; /* Check if x is in view rect */ if(x >= vx && x <= vx + swidth) { subViewSwitch(v, -1, False); break; } vx += swidth; } } break; /* }}} */ } } } } /* }}} */