📄 look-next.c
字号:
need_redraw = change_hilite (w, filelist_handle_mouse (w, cache, cwevent->y)); handled = 1; } break; case FocusIn: w->options |= BUTTON_HIGHLIGHT; need_redraw = 1; handled = 1; break; case FocusOut: w->options &= ~BUTTON_HIGHLIGHT; need_redraw = 1; handled = 1; break; case EnterNotify: /* we simply let our parent to process it */ case LeaveNotify: cwevent->ident = w->ident; break; case KeyPress: { int move_to = filelist_handle_keypress (w, cache, cwevent->command); if (move_to >= 0) { need_redraw = change_hilite (w, move_to); handled = 1; } else { switch (cwevent->command) { case CK_Left: case CK_Right: case CK_Home: case CK_End: case CK_Enter: case CK_BackSpace: cwevent->ident = w->ident; return 1; default: if (cwevent->insert > 0) { cwevent->ident = w->ident; return 1; } } } } break; default: return handled; } if (need_redraw || cwevent->double_click) cwevent->ident = w->ident; if ((xevent->type == Expose && !xevent->xexpose.count) || need_redraw) render_NeXT_filelist (w); return handled;}/* }}} file list stuff *//* {{{ file browser stuff *//*****************************************************************//* Miscellaneous read only text widget for dynamic text *//*****************************************************************/static void render_dyn_text (CWidget * wdt){ Window win = wdt->winid; char text[1024], *p, *q; int y, x = 0, w = wdt->width; int color = 0; int new_line = 1; CSetColor (COLOR_LIGHT); CRectangle (win, 1, 1, w - 2, wdt->height - 2); CSetColor (COLOR_BLACK); CSetBackgroundColor (COLOR_LIGHT); y = 1; /* bevel */ if ((q = wdt->text) == NULL) return; CPushFont ("widget", 0); for (;;) { long len; CSetColor (color_palette (color)); /* looking for control characters */ for (p = q; *p && *p >= ' '; p++); len = min ((unsigned long) p - (unsigned long) q, 1023); if (new_line) { if (wdt->options & TEXT_CENTRED) x = (w - (TEXT_RELIEF + 1) * 2 - CImageTextWidth (q, len)) / 2; else x = 0; new_line = 0; } if (!*p) { /* last line */ drawstring_xy (win, TEXT_RELIEF + 1 + x, TEXT_RELIEF + y, q); break; } else { memcpy (text, q, len); text[len] = 0; drawstring_xy (win, TEXT_RELIEF + 1 + x, TEXT_RELIEF + y, text); x += CImageTextWidth (q, len); } if (*p == '\n') { new_line = 1; y += FONT_PIX_PER_LINE; /* next line */ } else if (*p == 28) color = (int) '\n'; else color = *p; color %= 27; q = p + 1; } CPopFont (); render_bevel (win, 0, 0, w - 1, wdt->height - 1, 1, 1);}/*-----------------------------------------------------------------------*/static int eh_dyn_text (CWidget * w, XEvent * xevent, CEvent * cwevent){ switch (xevent->type) { case Expose: if (!xevent->xexpose.count) render_dyn_text (w); break; } return 0;}static CWidget *CDrawDynText (const char *identifier, Window parent, int x, int y, int width, int rows, const char *fmt,...){ va_list pa; char *str; int w, h; CWidget *wdt; va_start (pa, fmt); str = vsprintf_alloc (fmt, pa); va_end (pa); CPushFont ("widget", 0); CTextSize (&w, &h, str); if (width != AUTO_WIDTH && width) w = width; else w += TEXT_RELIEF * 2 + 2; if (rows != AUTO_HEIGHT && rows) { CTextSize (0, &h, "Ty~g$V|&^.,/_'I}[@"); h = (h + FONT_OVERHEAD) * rows; } h += TEXT_RELIEF * 2 + 2; wdt = CSetupWidget (identifier, parent, x, y, w, h, C_TEXT_WIDGET, INPUT_EXPOSE, COLOR_FLAT, 0); wdt->text = (char *) strdup (str); wdt->eh = eh_dyn_text; free (str); set_hint_pos (x + w + WIDGET_SPACING, y + h + WIDGET_SPACING); CPopFont (); return wdt;}static CWidget *CRedrawDynText (const char *identifier, const char *fmt,...){ va_list pa; char *str; CWidget *wdt;#if 0 int w, h;#endif wdt = CIdent (identifier); if (!wdt) return 0; va_start (pa, fmt); str = vsprintf_alloc (fmt, pa); va_end (pa); if (wdt->text) free (wdt->text); wdt->text = (char *) strdup (str); render_dyn_text (wdt); free (str); return wdt;}/******************************************************************//* NeXT Directory Tree stuff *//******************************************************************/typedef struct NeXTDir { struct NeXTDir *next, *prev; char *name; char *filter; long cursor; long current; long firstline; struct file_entry *list;} NeXTDir;typedef struct NeXTDirTree { NeXTDir *first, *last, *selected; NeXTDir *discarded; /* when we chdir - it will store previos tail */ int pos; int numdirs; int numpanes; char *path; int path_length; int dirty; /* can't change dirs - need to redraw widgets first */} NeXTDirTree;extern Bool is_directory (struct file_entry *directentry, int line_number);static NeXTDir *create_dir_elem (char *name, int name_len){ NeXTDir *dir; dir = (NeXTDir *) calloc (sizeof (NeXTDir), 1); dir->prev = dir->next = NULL; dir->filter = (char *) strdup ("*"); dir->current = -1; dir->list = NULL; if (name == NULL || name_len == 0) { /* root directory then */ dir->name = (char *) strdup (""); } else { dir->name = malloc (name_len + 1); strncpy (dir->name, name, name_len); dir->name[name_len] = '\0'; } return dir;}static void destroy_dir_elem (NeXTDir ** dir){ if (dir) { if (*dir) { if ((*dir)->filter) free ((*dir)->filter); if ((*dir)->name) free ((*dir)->name); if ((*dir)->list) free ((*dir)->list); memset (*dir, 0x00, sizeof (NeXTDir)); /* just in case */ free (*dir); *dir = NULL; } }}static NeXTDirTree *create_dir_tree (const char *path, int numpanes){ NeXTDirTree *tree = NULL; char *ptr = 0;#if 0 char *next; int i;#endif tree = (NeXTDirTree *) calloc (sizeof (NeXTDirTree), 1); if (ptr == NULL) { /* defaulting to the root */ tree->path_length = 1; tree->path = (char *) strdup ("/"); tree->first = tree->last = tree->selected = create_dir_elem ("", 0); } else { tree->path_length = strlen (path); tree->path = malloc (tree->path_length + 1); strcpy (tree->path, path); ptr = tree->path; if (*ptr == '/') { tree->first = tree->last = tree->selected = create_dir_elem ("", 0); tree->numdirs++; } while (*ptr) { int len = 0; while (*(ptr + len) && *(ptr + len) != '/') len++; if (len) { tree->selected = create_dir_elem (ptr, len); if (tree->last == NULL) tree->first = tree->last = tree->selected; else { tree->selected->prev = tree->last; tree->last->next = tree->selected; tree->last = tree->selected; } tree->numdirs++; } ptr += len; if (*ptr) ptr++; /* skipping / */ } } tree->numpanes = numpanes; tree->discarded = NULL; if (tree->selected == NULL) tree->selected = tree->last; tree->pos = tree->numdirs - tree->numpanes; if (tree->pos < 0) tree->pos = 0; return tree;}static void destroy_dir_chain (NeXTDir ** start){ NeXTDir *dir; for (dir = *start; dir; dir = *start) { *start = dir->next; destroy_dir_elem (&dir); }}static void destroy_dir_tree (NeXTDirTree ** tree){ if (tree) { destroy_dir_chain (&((*tree)->first)); destroy_dir_chain (&((*tree)->discarded)); free (*tree); *tree = NULL; }}static char *get_dir_path (NeXTDirTree * tree, NeXTDir * dir, char *buffer){ register NeXTDir *d; register char *ptr1 = buffer, *ptr2; if (!ptr1 || !tree || !dir) return NULL; for (d = tree->first; d && d != dir; d = d->next) { *(ptr1++) = '/'; ptr2 = d->name; if (*ptr2) while (*ptr2) *(ptr1++) = *(ptr2++); else /* we don't really want //, even thou it is not a violation */ ptr1--; } *ptr1 = '\0'; return buffer;}static struct file_entry *read_dir_filelist (NeXTDir * dir, char *path){ if (dir && path) { register int k; char *next_dir = NULL; CHourGlass (CFirstWindow); if (dir->list) free (dir->list); dir->list = get_file_entry_list (path, FILELIST_ALL_FILES, (dir->filter) ? dir->filter : "*"); if (dir->next) next_dir = dir->next->name; dir->current = -1; if (dir->list && next_dir) { for (k = 0; !(dir->list[k].options & FILELIST_LAST_ENTRY); k++) if (is_directory (dir->list, k)) if (strcmp (dir->list[k].name, next_dir) == 0) { dir->current = k; break; } } dir->cursor = dir->firstline = (dir->current >= 0) ? dir->current : 0; CUnHourGlass (CFirstWindow); } return dir->list;}static void update_tree_integrity (NeXTDirTree * tree, NeXTDir * selected){ NeXTDir *t; tree->selected = NULL; tree->numdirs = 0; tree->path_length = 0; for (t = tree->first; t; t = t->next) { tree->last = t; if (selected == t) tree->selected = selected; tree->numdirs++; tree->path_length += 1 + strlen (t->name); } tree->path_length++; tree->pos = tree->numdirs - tree->numpanes; if (tree->pos < 0) tree->pos = 0; if (tree->selected == NULL) tree->selected = tree->last;}static void change_dir (NeXTDirTree * tree, NeXTDir * dir, long item_num){ struct file_entry *item; NeXTDir *tmp; if (!tree || tree->dirty || !dir || item_num < 0) return; item = &(dir->list[item_num]); if (item->name[0] == '.') { if (item->name[1] == '\0') return; else if (item->name[1] == '.' && item->name[2] == '\0') { /* poping Up */ if (dir->prev == NULL) return; dir = dir->prev; if (tree->discarded) destroy_dir_chain (&(tree->discarded)); tree->discarded = dir->next; dir->next = NULL; tree->dirty = 1; update_tree_integrity (tree, dir); return; } } if (tree->discarded) { if (tree->discarded->prev == dir && strcmp (tree->discarded->name, item->name) == 0) { tmp = dir->next; dir->next = tree->discarded; tree->discarded = tmp; } else { destroy_dir_chain (&(tree->discarded)); tree->discarded = dir->next; dir->next = NULL; } } else { tree->discarded = dir->next; dir->next = NULL; } if (dir->next == NULL) { dir->next = create_dir_elem (item->name, strlen (item->name)); dir->next->prev = dir; } tree->dirty = 1; dir->current = item_num; /* taking some precautions so not to destroy tree integrity */ update_tree_integrity (tree, dir);}static char *get_full_filename (NeXTDirTree * tree, NeXTDir * dir, long item){ char *buffer, *path_tail; if (!tree || item < 0 || !dir || !(dir->list)) return NULL; buffer = malloc (tree->path_length + 1 + strlen (dir->list[item].name) + 1); get_dir_path (tree, dir, buffer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -