summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvictor <victor@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2005-02-05 17:52:37 +0800
committervictor <victor@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2005-02-05 17:52:37 +0800
commit6f1f6cff95aced193cf52c1324e4d485ce83498c (patch)
tree94e668042ceb6150baf5b83c7f7dd4f0d16a2287
parent6ca800ae0a303124ffd12ca4a712b6cdb01e69e7 (diff)
downloadpttbbs-victor.edit.tar
pttbbs-victor.edit.tar.gz
pttbbs-victor.edit.tar.bz2
pttbbs-victor.edit.tar.lz
pttbbs-victor.edit.tar.xz
pttbbs-victor.edit.tar.zst
pttbbs-victor.edit.zip
remove branch victor.solarisvictor.edit
add a new branch victor.edit (already lots of work in it) * refactoring, refactoring, and refactoring * documentation, documentation, and documentation * bug hunting 1.undelete_line segfault 2.string shifting segfault * behavior changing 1.cursor_to_prev_word (more user friendly) 2.disable Ctrl('_') feature, which is expensive (513 bytes per vedit) but not well-known. (I'm still observe people's behavior, but hopefully it's going to be removed.) * less memory usage, and fixing possible memory leak. git-svn-id: http://opensvn.csie.org/pttbbs/branches/victor.edit@2466 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rwxr-xr-xdocs/proto/cdoc2
-rw-r--r--include/proto.h4
-rw-r--r--mbbsd/edit.c1874
-rw-r--r--mbbsd/screen.c24
4 files changed, 1184 insertions, 720 deletions
diff --git a/docs/proto/cdoc b/docs/proto/cdoc
index 6759e84c..60f29a50 100755
--- a/docs/proto/cdoc
+++ b/docs/proto/cdoc
@@ -64,7 +64,7 @@ sub grep_desc
$out = $2;
$out =~ s#^/\*\*##;
$out =~ s#\s*\*/$##;
- $out =~ s/^\s*\* / /mg;
+ $out =~ s/^\s*\* ?/ /mg;
push @buffer, { type => 'comment', data => $out };
}
elsif ($3) {
diff --git a/include/proto.h b/include/proto.h
index ab551ae6..2088b51f 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -478,6 +478,7 @@ char *genpasswd(char *pw);
void mouts(int y, int x, char *str);
void move(int y, int x);
void outs(const char *str);
+void outs_n(const char *str, int n);
void clrtoeol(void);
void clear(void);
void refresh(void);
@@ -491,7 +492,8 @@ void redoln(void);
void clrtoline(int line);
void standout(void);
void standend(void);
-int edit_outs(const char *text);
+void edit_outs(const char *text);
+void edit_outs_n(const char *text, int n);
void outch(unsigned char c);
void rscroll(void);
void scroll(void);
diff --git a/mbbsd/edit.c b/mbbsd/edit.c
index 310fd7b3..db6ef395 100644
--- a/mbbsd/edit.c
+++ b/mbbsd/edit.c
@@ -1,5 +1,6 @@
/* $Id$ */
-/* edit.c, ¥Î¨Ó´£¨Ñ bbs¤Wªº¤å¦r½s¿è¾¹, §Y ve.
+/**
+ * edit.c, ¥Î¨Ó´£¨Ñ bbs¤Wªº¤å¦r½s¿è¾¹, §Y ve.
* ²{¦b³o¤@­Ó¬O´c·d¹Lªºª©¥», ¤ñ¸û¤£Ã­©w, ¥Î¤ñ¸û¦hªº cpu, ¦ý¬O¥i¥H¬Ù¤U³\¦h
* ªº°O¾ÐÅé (¥H Ptt¬°¨Ò, ¦b¤E¤d¤H¤W¯¸ªº®É­Ô, ¬ù¥i¬Ù¤U 50MB ªº°O¾ÐÅé)
* ¦pªG±z»{¬°¡u®³ cpu´«°O¾ÐÅé¡v¨Ã¤£¦X¥G±zªº¶·¨D, ±z¥i¥H¦Ò¼{§ï¨Ï¥Î­×¥¿«eªº
@@ -18,6 +19,12 @@
* ³o­Óª©¥»¦ü¥GÁÙ¦³¦a¤è¨S¦³­×¥¿¦n, ¥i¯à¾É­P segmentation fault .
*/
#include "bbs.h"
+
+/**
+ * data Äæ¦ìªº¥Îªk:
+ * ¨C¦¸ allocate ¤@­Ó textline_t ®É¡A·|°tµ¹¥L (sizeof(textline_t) + string
+ * length - 1) ªº¤j¤p¡C¦p¦¹¥iª½±µ¦s¨ú data ¦Ó¤£»ÝÃB¥~ªº malloc¡C
+ */
typedef struct textline_t {
struct textline_t *prev;
struct textline_t *next;
@@ -29,51 +36,117 @@ typedef struct textline_t {
} textline_t;
#define KEEP_EDITING -2
-#define BACKUP_LIMIT 100
enum {
NOBODY, MANAGER, SYSOP
};
+
+/**
+ * ³o­Ó»¡©ú·|±N¾ã­Ó edit.c ¹B§@ªº·§©À±a¹L¡A¥D­n·|±q editor_internal_t ªº
+ * data structure ½Í°_¡C¹ï©ó¨C¤@­Ó data member ªº¸Ô²Ó¥\¯à¡A½Ð¨£ sturcture
+ * ¤¤ªºµù¸Ñ¡C
+ *
+ * ¤å³¹ªº¤º®e (¥H¤UºÙ content) ¥H¡u¦æ¡v¬°³æ¦ì¡A¥D­n¥H firstline, lastline,
+ * totaln ¨Ó°O¿ý¡C
+ *
+ * User ¦bµe­±¤¤¬Ý¨ìªºµe­±¡A¸m©ó¤@­Ó¡u window ¡v¤¤¡A³o­Ó window ·|¦b
+ * content ¤W²¾°Ê¡Awindow ¸Ì­±ªº½d³ò§Y¬°­n show ¥X¨Óªº½d³ò¡C¥¦¥Î¤F¤£¤Ö
+ * Äæ¦ì¨Ó°O¿ý¡A¥]¬A currline, top_of_win, currln, currpnt, curr_window_line,
+ * edit_margin¡CÅã¥Ü¥X¨Óªº®ÄªG·íµM¤£¥u¬O¾a³o´X­Ó¸ê®Æ¡AÁÙ·|¸ò¨ä¥LÄæ¦ì¦³¥æ¤¬
+ * §@¥Î¡A¨Ò¦p ±m¦â½s¿è¼Ò¦¡¡B¯S®í²Å¸¹½s¿è µ¥µ¥¡C¨ä¤¤³Ì½ÆÂøªº³¡¤À¬O¦b¿ï¨ú block
+ * ¡]¨£«á¡^ªº®É­Ô¡C¤ñ¸û¤£ª½Ä±ªº¦æ¬°¬O¡G°£«D´å¼Ð¦b¶}©l¿ï¨ú¸ò¥Ø«e¡]µ²§ô¡^ªº¦ì¸m
+ * ¬O¦P¤@­Ó¡]¦¹®É³o­Ó½d³ò¬O¿ï¨úªº½d³ò¡^¡A§_«h´N¬O±q¶}©l¨º¤@¦C¤@ª½¨ì¥Ø«e¡]µ²§ô¡^
+ * ³o¤@¦C¡C
+ *
+ * editor ªº¨Ï¥Î¤W¥Ø«e¦³¤­ºØ inclusive ªº mode¡G
+ * insert mode:
+ * ´¡¤J/¨ú¥N
+ * ansi mode:
+ * ±m¦â½s¿è
+ * indent mode:
+ * ¦Û°ÊÁY±Æ
+ * phone mode:
+ * ¯S®í²Å¸¹½s¿è
+ * raw mode:
+ * ignore Ctrl('S'), Ctrl('Q'), Ctrl('T')
+ * ÃÙ¤ê: ³o¦³¤°»ò¥Î?
+ *
+ * editor ¤ä´©¤F°Ï¶ô¿ï¾Üªº¥\¯à¡]¦h¦æ¿ï¨ú ©Î ³æ¦æ¤¤ªº¤ù¬q¡^¡A¹ï©ó¤@­Ó selected
+ * block¡A¥i¥H cut, copy, cancel, ©ÎªÌ¦s¨ì¼È¨úÀÉ¡A¬Æ¦Ü¬O©¹¥ª/¥k shift¡C¸Ô¨£
+ * block_XXX¡C
+ *
+ * ¥Î Ctrl('Y') §R°£ªº¨º¤@¦æ·|³Q°O¨ì deleted_line ³o­ÓÄæ¦ì¤¤¡Cundelete_line()
+ * ¥i¥H°µ undelete ªº°Ê§@¡C deleted_line ªì©l­È¬° NULL¡A¨C¦¸¥u¤¹³\¦s¤@¦æ¡A©Ò¥H
+ * ¦b¦s¤U¨Ó®É¡Aµo²{­È¤£¬° NULL ·|¥ý°µ free ªº°Ê§@¡Ceditor µ²§ô®É¡A¦b
+ * edit_buffer_destructor() ¤¤¦pªGµo²{¦³ deleted_line¡A·|¦b³oÃäÄÀ©ñ±¼¡C¨ä¥L¦a
+ * ¤è¤]¦³¬Û¦Pªº§@ªk¡A¨Ò¦p searched_string¡Csearched_string ¬O¦b·j´M¤å³¹¤º®e
+ * ®É¡A­n´M§äªº key word¡C
+ *
+ * ÁÙ¦³¤@­Ó¦³½ìªº¯SÂI¡A¡u¬A¸¹¤Ç°t¡v¡I¦æ¬°´N¦p¦P¦b vim ¸Ì­±¤@¼Ë¡C§c¡A·íµM¨S¨º
+ * »ò±j°Õ¡A¦ý¦Ü¤Ö¦b§t¦³ c-style comment ¸ò c-style string ®É¬O¹ïªº³á¡C³o­Ó°Ê
+ * §@©w¸q©ó match_paren() ¤¤¡C
+ *
+ * ¥t¥~¡A¦pªG¦³»Ý­n·s¼W·sªºÄæ¦ì¡A½Ð±Nªì©l¤Æ¡]¦³»Ý­nªº¸Ü¡^ªº°Ê§@¼g¦b
+ * edit_buffer_constructor ¤¤¡C·íµM¤]¦³­Ó edit_buffer_destructor ¥i¥H¨Ï¥Î¡C
+ *
+ * ¦¹¥~¡A¬°¤F´£¨Ñ¤@­Ó reentrant ªº editor¡Aprev «ü¦V«e¤@­Ó editor ªº
+ * editor_internal_t¡Center_edit_buffer ¸ò exit_edit_buffer ´£¨Ñ¶i¥Xªº¤¶­±¡A
+ * ¸Ì­±¤À§O·|©I¥s constructor ¸ò destructor¡C
+ *
+ * Victor Hsieh <victor@csie.org>
+ * Thu, 03 Feb 2005 15:18:00 +0800
+ */
typedef struct editor_internal_t {
- textline_t *firstline;
- textline_t *lastline;
- textline_t *currline;
- textline_t *blockline;
- textline_t *top_of_win;
- textline_t *deleted_lines;
-
- short currpnt, currln, totaln;
- short curr_window_line;
- short edit_margin;
- short blockln;
- short blockpnt;
- char insert_c;
-
- char phone_mode;
- char phone_mode0;
- char insert_character :1;
- char my_ansimode :1;
+
+ textline_t *firstline; /* first line of the article. */
+ textline_t *lastline; /* last line of the article. */
+
+ textline_t *currline; /* current line of the article(window). */
+ textline_t *blockline; /* the first selected line of the block. */
+ textline_t *top_of_win; /* top line of the article in the window. */
+
+ textline_t *deleted_line; /* deleted line. Just keep one deleted line. */
+
+ short currln; /* current line of the article. */
+ short currpnt; /* current column of the article. */
+ short totaln; /* total lines of the article. */
+ short curr_window_line; /* current line to the window. */
+ short last_margin;
+ short edit_margin; /* when the cursor moves out of range (say,
+ t_columns), shift this length of the string
+ so you won't see the first edit_margin-th
+ character. */
+ short lastindent;
+ short blockln; /* the row you started to select block. */
+ short blockpnt; /* the column you started to select block. */
+ char insert_c; /* insert this character when shift something
+ in order to compensate the new space. */
+ char last_phone_mode;
+
char ifuseanony :1;
char redraw_everything :1;
- char raw_mode :1;
- char line_dirty :1;
+
+ char insert_mode :1;
+ char ansimode :1;
char indent_mode :1;
+ char phone_mode :1;
+ char raw_mode :1;
+
+ char *searched_string;
+ char *(*substr_fp) ();
struct editor_internal_t *prev;
} editor_internal_t;
-// ?? } __attribute__ ((packed))
+// } __attribute__ ((packed))
-//static editor_internal_t *edit_buf_head = NULL;
static editor_internal_t *curr_buf = NULL;
-static char editline[WRAPMARGIN + 2];
-
static const char fp_bak[] = "bak";
-static char *BIG5[13] = {
+static const char *BIG5[13] = {
"¡A¡F¡G¡B¡N¡C¡H¡I¡E¡T¡]¡^¡©¡ª¡«¡¬",
"¢b¢c¢d¢e¢f¢g¢h¢i¢j¢k¢l¢m¢n¢o¢pùþ ",
"¡³¡ó¡·¡´¡¸¡¹¡¼¡½¡¿¡¶¡¾¡µ¡º¡»¡ð¡ñ",
@@ -89,7 +162,7 @@ static char *BIG5[13] = {
"¢¹¢º¢»¢¼¢½¢¾¢¿¢À¢Á¢Â"
};
-static char *BIG_mode[13] = {
+static const char *BIG_mode[13] = {
"¼ÐÂI",
"¹Ï¶ô",
"¼Ð°O",
@@ -105,7 +178,7 @@ static char *BIG_mode[13] = {
"¼Æ¦r"
};
-static char *table[8] = {
+static const char *table[8] = {
"¢x¢w¢|¢r¢}¢u¢q¢t¢z¢s¢{",
"ùø¢¤ùãùäùåùàùáùâùÝùÞùß",
"ùø¢wùõùöù÷ùòùóùôùïùðùñ",
@@ -116,7 +189,7 @@ static char *table[8] = {
"¢x¢¤ùìùíù¢¦¢§ùæùçùè"
};
-static char *table_mode[6] = {
+static const char *table_mode[6] = {
"ª½¨¤",
"Ås©·",
"¢q",
@@ -130,34 +203,59 @@ static char *table_mode[6] = {
static void
indigestion(int i)
{
- fprintf(stderr, "ÄY­«¤º¶Ë %d\n", i);
+ char buf[64];
+ sprintf(buf, "ÄY­«¤º¶Ë (%d)\n", i);
+ vmsg(buf);
+ u_exit("EDITOR FAILED");
+ exit(0);
}
-static void init_edit_buffer(editor_internal_t *buf)
+static inline void
+edit_buffer_constructor(editor_internal_t *buf)
{
/* all unspecified columns are 0 */
buf->blockln = -1;
buf->insert_c = ' ';
- buf->insert_character = 1;
+ buf->insert_mode = 1;
buf->redraw_everything = 1;
+ buf->lastindent = -1;
}
-static void enter_edit_buffer(void)
+static inline void
+enter_edit_buffer(void)
{
editor_internal_t *p = curr_buf;
curr_buf = (editor_internal_t *)malloc(sizeof(editor_internal_t));
memset(curr_buf, 0, sizeof(editor_internal_t));
curr_buf->prev = p;
+ edit_buffer_constructor(curr_buf);
+}
+
+static inline void
+edit_buffer_destructor(void)
+{
+ if (curr_buf->deleted_line != NULL)
+ free(curr_buf->deleted_line);
+
+ if (curr_buf->searched_string != NULL)
+ free(curr_buf->searched_string);
}
-static void exit_edit_buffer(void)
+static inline void
+exit_edit_buffer(void)
{
editor_internal_t *p = curr_buf;
+
+ edit_buffer_destructor();
curr_buf = p->prev;
free(p);
}
-/* Thor: ansi ®y¼ÐÂà´« for color ½s¿è¼Ò¦¡ */
+/**
+ * transform position ansix in an ansi string of textline_t to the same
+ * string without escape code.
+ * @return position in the string without escape code.
+ */
static int
ansi2n(int ansix, textline_t * line)
{
@@ -182,6 +280,10 @@ ansi2n(int ansix, textline_t * line)
return tmp - data;
}
+/**
+ * opposite to ansi2n, according to given textline_t.
+ * @return position in the string with escape code.
+ */
static short
n2ansi(short nx, textline_t * line)
{
@@ -209,54 +311,78 @@ n2ansi(short nx, textline_t * line)
}
/* ¿Ã¹õ³B²z¡G»²§U°T®§¡BÅã¥Ü½s¿è¤º®e */
+
+static inline void
+show_phone_mode_panel(void)
+{
+ int i;
+
+ move(b_lines - 1, 0);
+ clrtoeol();
+
+ if (curr_buf->last_phone_mode < 20) {
+ int len;
+ prints("\033[1;46m¡i%s¿é¤J¡j ", BIG_mode[curr_buf->last_phone_mode - 1]);
+ len = strlen(BIG5[curr_buf->last_phone_mode - 1]) / 2;
+ for (i = 0; i < len; i++)
+ prints("\033[37m%c\033[34m%2.2s",
+ i + 'A', BIG5[curr_buf->last_phone_mode - 1] + i * 2);
+ for (i = 0; i < 16 - len; i++)
+ outs(" ");
+ outs("\033[37m `1~9-=¤Á´« Zªí®æ\033[m");
+ }
+ else {
+ prints("\033[1;46m¡iªí®æø»s¡j /=%s *=%s§Î ",
+ table_mode[(curr_buf->last_phone_mode - 20) / 4],
+ table_mode[(curr_buf->last_phone_mode - 20) % 4 + 2]);
+ for (i = 0;i < 11;i++)
+ prints("\033[37m%c\033[34m%2.2s", i ? i + '/' : '.',
+ table[curr_buf->last_phone_mode - 20] + i * 2);
+ outs("\033[37m Z¤º½X \033[m");
+ }
+}
+
+/**
+ * Show the bottom status/help bar, and BIG5/table in phone_mode.
+ */
static void
edit_msg()
{
- const char *edit_mode[2] = {"¨ú¥N", "´¡¤J"};
- register int n = curr_buf->currpnt;
- int i;
+ int n = curr_buf->currpnt;
- if (curr_buf->my_ansimode) /* Thor: §@ ansi ½s¿è */
+ if (curr_buf->ansimode) /* Thor: §@ ansi ½s¿è */
n = n2ansi(n, curr_buf->currline);
- n++;
- if(curr_buf->phone_mode) {
- move(b_lines - 1, 0);
- clrtoeol();
- if(curr_buf->phone_mode < 20) {
- prints("\033[1;46m¡i%s¿é¤J¡j ", BIG_mode[curr_buf->phone_mode - 1]);
- for (i = 0;i < 16;i++)
- if (i < strlen(BIG5[curr_buf->phone_mode - 1]) / 2)
- prints("\033[37m%c\033[34m%2.2s",
- i + 'A', BIG5[curr_buf->phone_mode - 1] + i * 2);
- else
- outs(" ");
- outs("\033[37m `-=¤Á´« Zªí®æ \033[m");
- }
- else {
- prints("\033[1;46m¡iªí®æø»s¡j /=%s *=%s§Î ",
- table_mode[(curr_buf->phone_mode - 20) / 4],
- table_mode[(curr_buf->phone_mode - 20) % 4 + 2]);
- for (i = 0;i < 11;i++)
- prints("\033[37m%c\033[34m%2.2s", i ? i + '/' : '.',
- table[curr_buf->phone_mode - 20] + i * 2);
- outs("\033[37m Z¤º½X \033[m");
- }
- }
+
+ if (curr_buf->phone_mode)
+ show_phone_mode_panel();
+
move(b_lines, 0);
clrtoeol();
- prints("\033[%sm ½s¿è¤å³¹ \033[31;47m (^Z)\033[30m»¡©ú "
+ prints("\033[37;44m ½s¿è¤å³¹ \033[31;47m (^Z)\033[30m»¡©ú "
"\033[31;47m(^P)\033[30m²Å¸¹ "
"\033[31;47m(^G)\033[30m´¡¤J¹Ï¤å®w \033[31m(^X,^Q)"
"\033[30mÂ÷¶}ùø%s¢x%c%c%c%cùø %3d:%3d \033[m",
- "37;44",
- edit_mode[curr_buf->insert_character ? 1 : 0],
- curr_buf->my_ansimode ? 'A' : 'a',
+ curr_buf->insert_mode ? "´¡¤J" : "¨ú¥N",
+ curr_buf->ansimode ? 'A' : 'a',
curr_buf->indent_mode ? 'I' : 'i',
curr_buf->phone_mode ? 'P' : 'p',
curr_buf->raw_mode ? 'R' : 'r',
- curr_buf->currln + 1, n);
+ curr_buf->currln + 1, n + 1);
+}
+
+/**
+ * return the middle line of the window.
+ */
+static inline int
+middle_line(void)
+{
+ return p_lines / 2 + 1;
}
+/**
+ * Return the previous 'num' line. Stop at the first line if there's
+ * not enough lines.
+ */
static textline_t *
back_line(textline_t * pos, int num)
{
@@ -267,10 +393,16 @@ back_line(textline_t * pos, int num)
pos = item;
curr_buf->currln--;
}
+ else
+ break;
}
return pos;
}
+/**
+ * Return the next 'num' line. Stop at the last line if there's not
+ * enough lines.
+ */
static textline_t *
forward_line(textline_t * pos, int num)
{
@@ -281,12 +413,96 @@ forward_line(textline_t * pos, int num)
pos = item;
curr_buf->currln++;
}
+ else
+ break;
}
return pos;
}
+/**
+ * move the cursor to the next line with ansimode fixed.
+ */
+static inline void
+cursor_to_next_line(void)
+{
+ short pos;
+
+ if (curr_buf->currline->next == NULL)
+ return;
+
+ curr_buf->currline = curr_buf->currline->next;
+ curr_buf->curr_window_line++;
+ curr_buf->currln++;
+
+ if (curr_buf->ansimode) {
+ pos = n2ansi(curr_buf->currpnt, curr_buf->currline->prev);
+ curr_buf->currpnt = ansi2n(pos, curr_buf->currline);
+ }
+ else {
+ curr_buf->currpnt = (curr_buf->currline->len > curr_buf->lastindent)
+ ? curr_buf->lastindent : curr_buf->currline->len;
+ }
+}
+
+/**
+ * opposite to cursor_to_next_line.
+ */
+static inline void
+cursor_to_prev_line(void)
+{
+ short pos;
+
+ if (curr_buf->currline->prev == NULL)
+ return;
+
+ curr_buf->curr_window_line--;
+ curr_buf->currln--;
+ curr_buf->currline = curr_buf->currline->prev;
+
+ if (curr_buf->ansimode) {
+ pos = n2ansi(curr_buf->currpnt, curr_buf->currline->next);
+ curr_buf->currpnt = ansi2n(pos, curr_buf->currline);
+ }
+ else {
+ curr_buf->currpnt = (curr_buf->currline->len > curr_buf->lastindent)
+ ? curr_buf->lastindent : curr_buf->currline->len;
+ }
+}
+
+static inline void
+window_scroll_down(void)
+{
+ curr_buf->curr_window_line = 0;
+
+ if (!curr_buf->top_of_win->prev)
+ indigestion(6);
+ else {
+ curr_buf->top_of_win = curr_buf->top_of_win->prev;
+ rscroll();
+ }
+}
+
+static inline void
+window_scroll_up(void)
+{
+ if (unlikely(!curr_buf->top_of_win->next))
+ indigestion(7);
+ else {
+ curr_buf->top_of_win = curr_buf->top_of_win->next;
+ if(curr_buf->phone_mode)
+ move(b_lines-1, 0);
+ else
+ move(b_lines, 0);
+ clrtoeol();
+ scroll();
+ }
+}
+
+/**
+ * Get the current line number in the window now.
+ */
static int
-getlineno()
+get_lineno_in_window()
{
int cnt = 0;
textline_t *p = curr_buf->currline;
@@ -298,18 +514,46 @@ getlineno()
return cnt;
}
-static char *
-killsp(char *s)
+/**
+ * shift given raw data s with length len to left by one byte.
+ */
+static void
+raw_shift_left(char *s, int len)
+{
+ int i;
+ for (i = 0; i < len && s[i] != 0; ++i)
+ s[i] = s[i + 1];
+}
+
+/**
+ * shift given raw data s with length len to right by one byte.
+ */
+static void
+raw_shift_right(char *s, int len)
+{
+ int i;
+ for (i = len - 1; i >= 0; --i)
+ s[i + 1] = s[i];
+}
+
+/**
+ * Return the pointer to the next non-space position.
+ */
+static char *
+next_non_space_char(char *s)
{
while (*s == ' ')
s++;
return s;
}
+/**
+ * allocate a textline_t with length length.
+ */
static textline_t *
alloc_line(short length)
{
- register textline_t *p;
+ textline_t *p;
if ((p = (textline_t *) malloc(length + sizeof(textline_t)))) {
memset(p, 0, length + sizeof(textline_t));
@@ -323,11 +567,25 @@ alloc_line(short length)
return NULL;
}
-/* append p after line in list. keeps up with last line */
+/**
+ * deleted_line will be assigned to 'line'. If deleted_line is not NULL,
+ * it'll be freed first.
+ */
+static inline void
+set_deleted_line(textline_t *line)
+{
+ if (curr_buf->deleted_line != NULL)
+ free(curr_buf->deleted_line);
+ curr_buf->deleted_line = line;
+}
+
+/**
+ * Insert p after line in list. Keeps up with last line
+ */
static void
-append(textline_t * p, textline_t * line)
+insert_line(textline_t *line, textline_t *p)
{
- register textline_t *n;
+ textline_t *n;
if ((p->next = n = line->next))
n->prev = p;
@@ -337,11 +595,9 @@ append(textline_t * p, textline_t * line)
p->prev = line;
}
-/*
- * delete_line deletes 'line' from the list, and maintains the lastline, and
- * firstline pointers.
+/**
+ * delete_line deletes 'line' from the line list.
*/
-
static void
delete_line(textline_t * line)
{
@@ -360,16 +616,14 @@ delete_line(textline_t * line)
p->next = n;
else
curr_buf->firstline = n;
- strcat(line->data, "\n");
- line->prev = curr_buf->deleted_lines;
- curr_buf->deleted_lines = line;
+
curr_buf->totaln--;
}
static int
ask(char *prompt)
{
- int ch;
+ int ch;
move(0, 0);
clrtoeol();
@@ -382,8 +636,14 @@ ask(char *prompt)
return (ch);
}
+/**
+ * Return the indent space number according to CURRENT line and the FORMER
+ * line. It'll be the first line contains non-space character.
+ * @return space number from the beginning to the first non-space character,
+ * return 0 if non or not in indent mode.
+ */
static int
-indent_spcs()
+indent_space()
{
textline_t *p;
int spcs;
@@ -393,23 +653,28 @@ indent_spcs()
for (p = curr_buf->currline; p; p = p->prev) {
for (spcs = 0; p->data[spcs] == ' '; ++spcs);
+ /* empty loop */
if (p->data[spcs])
return spcs;
}
return 0;
}
+/**
+ * adjustline(oldp, len);
+ * ¥Î¨Ó±N oldp «ü¨ìªº¨º¤@¦æ, ­«·s­×¥¿¦¨ len³o»òªø.
+ *
+ * In FreeBSD:
+ * ¦b³oÃä¤@¦@°µ¤F¨â¦¸ªº memcpy() , ²Ä¤@¦¸±q heap «þ¨ì stack ,
+ * §â­ì¨Ó°O¾ÐÅé free() «á, ¤S­«·s¦b stack¤W malloc() ¤@¦¸,
+ * µM«á¦A«þ¨©¦^¨Ó.
+ * ¥D­n¬O¥Î sbrk() Æ[¹î¨ìªºµ²ªG, ³o¼Ë¤l¤~¯uªº¯àÁY´î°O¾ÐÅé¥Î¶q.
+ * ¸Ô¨£ /usr/share/doc/papers/malloc.ascii.gz (in FreeBSD)
+ */
static textline_t *
adjustline(textline_t *oldp, short len)
{
- /* adjustline(oldp, len);
- * ¥Î¨Ó±N oldp «ü¨ìªº¨º¤@¦æ, ­«·s­×¥¿¦¨ len³o»òªø.
- * ¦b³oÃä¤@¦@°µ¤F¨â¦¸ªº memcpy() , ²Ä¤@¦¸±q heap «þ¨ì stack ,
- * §â­ì¨Ó°O¾ÐÅé free() «á, ¤S­«·s¦b stack¤W malloc() ¤@¦¸,
- * µM«á¦A«þ¨©¦^¨Ó.
- * ¥D­n¬O¥Î sbrk() Æ[¹î¨ìªºµ²ªG, ³o¼Ë¤l¤~¯uªº¯àÁY´î°O¾ÐÅé¥Î¶q.
- * ¸Ô¨£ /usr/share/doc/papers/malloc.ascii.gz (in FreeBSD)
- */
+ // XXX write a generic version ?
char tmpl[sizeof(textline_t) + WRAPMARGIN];
textline_t *newp;
memcpy(tmpl, oldp, oldp->len + sizeof(textline_t));
@@ -431,14 +696,18 @@ adjustline(textline_t *oldp, short len)
return newp;
}
-/* split 'line' right before the character pos */
+/**
+ * split 'line' right before the character pos
+ *
+ * @return the latter line after splitting
+ */
static textline_t *
split(textline_t * line, int pos)
{
if (pos <= line->len) {
register textline_t *p = alloc_line(WRAPMARGIN);
register char *ptr;
- int spcs = indent_spcs();
+ int spcs = indent_space();
curr_buf->totaln++;
@@ -447,11 +716,17 @@ split(textline_t * line, int pos)
memset(p->data, ' ', spcs);
p->data[spcs] = 0;
- strcat(p->data, (ptr = line->data + pos));
+
+ ptr = line->data + pos;
+ if (curr_buf->indent_mode)
+ ptr = next_non_space_char(ptr);
+ strcat(p->data + spcs, ptr);
ptr[0] = '\0';
- append(p, line);
+
+ insert_line(line, p);
line = adjustline(line, line->len);
if (line == curr_buf->currline && pos <= curr_buf->currpnt) {
+ // XXX never reached !? since line is a new allocated memory
curr_buf->currline = p;
if (pos == curr_buf->currpnt)
curr_buf->currpnt = spcs;
@@ -465,6 +740,12 @@ split(textline_t * line, int pos)
return line;
}
+/**
+ * Insert a character ch to current line.
+ *
+ * The line will be split if the length is >= WRAPMARGIN. It'll be split
+ * from the last space if any, or start a new line after the last character.
+ */
static void
insert_char(int ch)
{
@@ -477,16 +758,13 @@ insert_char(int ch)
indigestion(1);
return;
}
- if (curr_buf->currpnt < i && !curr_buf->insert_character) {
+ if (curr_buf->currpnt < i && !curr_buf->insert_mode) {
p->data[curr_buf->currpnt++] = ch;
/* Thor: ansi ½s¿è, ¥i¥Hoverwrite, ¤£»\¨ì ansi code */
- if (curr_buf->my_ansimode)
+ if (curr_buf->ansimode)
curr_buf->currpnt = ansi2n(n2ansi(curr_buf->currpnt, p), p);
} else {
- while (i >= curr_buf->currpnt) {
- p->data[i + 1] = p->data[i];
- i--;
- }
+ raw_shift_right(p->data + curr_buf->currpnt, i - curr_buf->currpnt + 1);
p->data[curr_buf->currpnt++] = ch;
i = ++(p->len);
}
@@ -512,6 +790,10 @@ insert_char(int ch)
}
}
}
+
+/**
+ * insert_char twice.
+ */
static void
insert_dchar(const char *dchar)
{
@@ -520,55 +802,78 @@ insert_dchar(const char *dchar)
}
static void
+insert_tab(void)
+{
+ do {
+ insert_char(' ');
+ } while (curr_buf->currpnt & 0x7);
+}
+
+/**
+ * Insert a string.
+ *
+ * All printable and '\033' will be directly printed out.
+ * '\t' will be printed to align every 8 byte.
+ * '\n' will split the line.
+ * The other character will be ignore.
+ */
+static void
insert_string(const char *str)
{
- int ch;
+ char ch;
while ((ch = *str++)) {
if (isprint2(ch) || ch == '\033')
insert_char(ch);
- else if (ch == '\t') {
- do {
- insert_char(' ');
- } while (curr_buf->currpnt & 0x7);
- } else if (ch == '\n')
+ else if (ch == '\t')
+ insert_tab();
+ else if (ch == '\n')
split(curr_buf->currline, curr_buf->currpnt);
}
}
-static int
-undelete_line()
+/**
+ * undelete the deleted line.
+ *
+ * return NULL if there's no deleted_line, otherwise, return currline.
+ */
+static textline_t *
+undelete_line(void)
{
- textline_t *p = curr_buf->deleted_lines;
editor_internal_t tmp;
- if (!curr_buf->deleted_lines)
- return 0;
+ if (!curr_buf->deleted_line)
+ return NULL;
- tmp.currline = curr_buf->currline;
tmp.top_of_win = curr_buf->top_of_win;
- tmp.currpnt = curr_buf->currpnt;
- tmp.currln = curr_buf->currln;
- tmp.curr_window_line = curr_buf->curr_window_line;
tmp.indent_mode = curr_buf->indent_mode;
+ tmp.curr_window_line = curr_buf->curr_window_line;
curr_buf->indent_mode = 0;
- insert_string(curr_buf->deleted_lines->data);
- curr_buf->indent_mode = tmp.indent_mode;
- curr_buf->deleted_lines = curr_buf->deleted_lines->prev;
- free(p);
+ curr_buf->currpnt = 0;
+ curr_buf->currln++;
+ insert_string(curr_buf->deleted_line->data);
+ insert_string("\n");
- curr_buf->currline = tmp.currline;
curr_buf->top_of_win = tmp.top_of_win;
- curr_buf->currpnt = tmp.currpnt;
- curr_buf->currln = tmp.currln;
+ curr_buf->indent_mode = tmp.indent_mode;
curr_buf->curr_window_line = tmp.curr_window_line;
- return 0;
+
+ curr_buf->currline = curr_buf->currline->prev;
+
+ if (curr_buf->currline->prev == NULL) {
+ curr_buf->top_of_win = curr_buf->currline;
+ curr_buf->currln = 0;
+ }
+ return curr_buf->currline;
}
/*
* 1) lines were joined and one was deleted 2) lines could not be joined 3)
* next line is empty returns false if: 1) Some of the joined line wrapped
+ *
+ * (It assumes line has WRAPMARGIN length of data. It seems to imply
+ * line == currline .)
*/
static int
join(textline_t * line)
@@ -578,7 +883,7 @@ join(textline_t * line)
if (!(n = line->next))
return YEA;
- if (!*killsp(n->data))
+ if (!*next_non_space_char(n->data))
return YEA;
ovfl = line->len + n->len - WRAPMARGIN;
@@ -588,6 +893,7 @@ join(textline_t * line)
delete_line(n);
return YEA;
} else {
+ // FIXME segfault
register char *s;
s = n->data + n->len - ovfl - 1;
@@ -622,29 +928,25 @@ delete_char()
register int len;
if ((len = curr_buf->currline->len)) {
- register int i;
- register char *s;
-
- if (curr_buf->currpnt >= len) {
+ if (unlikely(curr_buf->currpnt >= len)) {
indigestion(1);
return;
}
- for (i = curr_buf->currpnt, s = curr_buf->currline->data + i; i != len; i++, s++)
- s[0] = s[1];
+ raw_shift_left(curr_buf->currline->data + curr_buf->currpnt, curr_buf->currline->len - curr_buf->currpnt + 1);
curr_buf->currline->len--;
}
}
static void
-load_file(FILE * fp) /* NOTE it will fclose(fp) */
+load_file(FILE * fp)
{
+ char buf[WRAPMARGIN + 2];
int indent_mode0 = curr_buf->indent_mode;
assert(fp);
curr_buf->indent_mode = 0;
- while (fgets(editline, WRAPMARGIN + 2, fp))
- insert_string(editline);
- fclose(fp);
+ while (fgets(buf, sizeof(buf), fp))
+ insert_string(buf);
curr_buf->indent_mode = indent_mode0;
}
@@ -685,6 +987,7 @@ read_tmpbuf(int n)
getdata(b_lines - 1, 0, "½T©wŪ¤J¶Ü(Y/N)?[Y]", ans, sizeof(ans), LCECHO);
if (*ans != 'n' && (fp = fopen(fp_tmpbuf, "r"))) {
load_file(fp);
+ fclose(fp);
while (curr_buf->curr_window_line >= b_lines) {
curr_buf->curr_window_line--;
curr_buf->top_of_win = curr_buf->top_of_win->next;
@@ -733,6 +1036,7 @@ erase_tmpbuf()
/**
* ½s¿è¾¹¦Û°Ê³Æ¥÷
+ *(³Ì¦h³Æ¥÷ 512 ¦æ (?))
*/
void
auto_backup()
@@ -781,6 +1085,7 @@ restore_backup()
}
/* ¤Þ¥Î¤å³¹ */
+
static int
garbage_line(char *str)
{
@@ -876,7 +1181,9 @@ do_quote()
}
}
-/* ¼f¬d user ¤Þ¨¥ªº¨Ï¥Î */
+/**
+ * ¼f¬d user ¤Þ¨¥ªº¨Ï¥Î
+ */
static int
check_quote()
{
@@ -924,14 +1231,16 @@ read_file(char *fpath)
FILE *fp;
if ((fp = fopen(fpath, "r")) == NULL) {
- if ((fp = fopen(fpath, "w+"))) {
- fclose(fp);
+ int fd;
+ if ((fd = creat(fpath, 0600)) >= 0) {
+ close(fd);
return;
}
indigestion(4);
abort_bbs(0);
}
load_file(fp);
+ fclose(fp);
}
void
@@ -1012,7 +1321,7 @@ write_header(FILE * fp, int ifuseanony) // FIXME unused
}
save_title[72] = '\0';
- fprintf(fp, "¼ÐÃD: %s\n®É¶¡: %s\n", save_title, ctime4(&now));
+ fprintf(fp, "¼ÐÃD: %s\n®É¶¡: %s\n", save_title, ctime(&now));
}
void
@@ -1216,69 +1525,378 @@ write_file(char *fpath, int saveheader, int *islocal)
return aborted;
}
+static inline int
+has_block_selection(void)
+{
+ return curr_buf->blockln >= 0;
+}
+
+/**
+ * a block is continual lines of the article.
+ */
+/**
+ * stop the block selection.
+ */
static void
-display_buffer()
+block_cancel(void)
{
- register textline_t *p;
- register int i;
- int inblock;
- char buf[WRAPMARGIN + 2];
- int min, max;
+ if (has_block_selection()) {
+ curr_buf->blockln = -1;
+ curr_buf->redraw_everything = YEA;
+ }
+}
+
+static inline void
+setup_block_begin_end(textline_t **begin, textline_t **end)
+{
+ if (curr_buf->currln >= curr_buf->blockln) {
+ *begin = curr_buf->blockline;
+ *end = curr_buf->currline;
+ } else {
+ *begin = curr_buf->currline;
+ *end = curr_buf->blockline;
+ }
+}
+static inline void
+setup_block_begin_end_number(short *begin, short *end)
+{
if (curr_buf->currpnt > curr_buf->blockpnt) {
- min = curr_buf->blockpnt;
- max = curr_buf->currpnt;
+ *begin = curr_buf->blockpnt;
+ *end = curr_buf->currpnt;
} else {
- min = curr_buf->currpnt;
- max = curr_buf->blockpnt;
+ *begin = curr_buf->currpnt;
+ *end = curr_buf->blockpnt;
}
+}
+
+#define BLOCK_TRUNCATE 0
+#define BLOCK_APPEND 1
+/**
+ * save the selected block to file 'fname.'
+ * mode: BLOCK_TRUNCATE truncate mode
+ * BLOCK_APPEND append mode
+ */
+static void
+block_save_to_file(char *fname, int mode)
+{
+ textline_t *begin, *end;
+ char fp_tmpbuf[80];
+ FILE *fp;
+
+ if (!has_block_selection())
+ return;
+
+ setup_block_begin_end(&begin, &end);
+
+ setuserfile(fp_tmpbuf, fname);
+ if ((fp = fopen(fp_tmpbuf, mode == BLOCK_APPEND ? "a+" : "w+"))) {
+ if (begin == end && curr_buf->currpnt != curr_buf->blockpnt) {
+ char buf[WRAPMARGIN + 2];
+
+ if (curr_buf->currpnt > curr_buf->blockpnt) {
+ strlcpy(buf, begin->data + curr_buf->blockpnt, sizeof(buf));
+ buf[curr_buf->currpnt - curr_buf->blockpnt] = 0;
+ } else {
+ strlcpy(buf, begin->data + curr_buf->currpnt, sizeof(buf));
+ buf[curr_buf->blockpnt - curr_buf->currpnt] = 0;
+ }
+ fputs(buf, fp);
+ } else {
+ textline_t *p;
+
+ for (p = begin; p != end; p = p->next)
+ fprintf(fp, "%s\n", p->data);
+ fprintf(fp, "%s\n", end->data);
+ }
+ fclose(fp);
+ }
+}
+
+/**
+ * delete selected block
+ */
+static void
+block_delete(void)
+{
+ textline_t *begin, *end;
+
+ if (!has_block_selection())
+ return;
+
+ setup_block_begin_end(&begin, &end);
+
+ if (begin == end && curr_buf->currpnt != curr_buf->blockpnt) {
+ short min, max;
+
+ setup_block_begin_end_number(&min, &max);
+ strcpy(begin->data + min, begin->data + max);
+ begin->len -= max - min;
+ curr_buf->currpnt = min;
+
+ } else {
+#if 0
+ textline_t *p;
+
+ for (p = begin; p != end; p = p->next)
+ delete_line(p);
+ delete_line(end);
+
+ curr_buf->top_of_win = ;
+ curr_buf->curr_window_line -= (curr_buf->currln - curr_buf->blockln);
+ curr_buf->currpnt = 0;
+ curr_buf->currline = begin;
+#else
+ textline_t *p;
+
+ if (curr_buf->currln >= curr_buf->blockln) {
+ curr_buf->curr_window_line -= (curr_buf->currln - curr_buf->blockln);
+ if (curr_buf->curr_window_line < 0) {
+ curr_buf->curr_window_line = 0;
+ if (end->next)
+ (curr_buf->top_of_win = end->next)->prev = begin->prev;
+ else
+ curr_buf->top_of_win = (curr_buf->lastline = begin->prev);
+ }
+ curr_buf->currln -= (curr_buf->currln - curr_buf->blockln);
+ }
+
+ if (begin->prev)
+ begin->prev->next = end->next;
+ else if (end->next)
+ curr_buf->top_of_win = curr_buf->firstline = end->next;
+ else {
+ curr_buf->currline = curr_buf->top_of_win = curr_buf->firstline = curr_buf->lastline = alloc_line(WRAPMARGIN);
+ curr_buf->currln = curr_buf->curr_window_line = curr_buf->edit_margin = 0;
+ }
+
+ if (end->next)
+ (curr_buf->currline = end->next)->prev = begin->prev;
+ else if (begin->prev) {
+ curr_buf->currline = (curr_buf->lastline = begin->prev);
+ curr_buf->currln--;
+ if (curr_buf->curr_window_line > 0)
+ curr_buf->curr_window_line--;
+ }
+
+ for (p = begin; p != end; curr_buf->totaln--)
+ free((p = p->next)->prev);
+ free(end);
+ curr_buf->totaln--;
+
+ curr_buf->currpnt = 0;
+#endif
+ }
+}
+
+static void
+block_cut(void)
+{
+ if (!has_block_selection())
+ return;
+
+ block_save_to_file("buf.0", BLOCK_TRUNCATE);
+ block_delete();
+
+ curr_buf->blockln = -1;
+ curr_buf->redraw_everything = YEA;
+}
+
+static void
+block_copy(void)
+{
+ if (!has_block_selection())
+ return;
+
+ block_save_to_file("buf.0", BLOCK_TRUNCATE);
+
+ curr_buf->blockln = -1;
+ curr_buf->redraw_everything = YEA;
+}
+
+static void
+block_prompt(void)
+{
+ char fp_tmpbuf[80];
+ char tmpfname[] = "buf.0";
+ char mode[2];
+
+ move(b_lines - 1, 0);
+ clrtoeol();
+
+ if (!getdata(b_lines - 1, 0, "§â°Ï¶ô²¾¦Ü¼È¦sÀÉ (0:Cut, 5:Copy, 6-9, q: Cancel)[0] ", tmpfname + 4, 4, LCECHO))
+ tmpfname[4] = '0';
+
+ if (tmpfname[4] < '0' || tmpfname[4] > '9')
+ goto cancel_block;
+
+ if (tmpfname[4] == '0') {
+ block_cut();
+ return;
+ }
+ else if (tmpfname[4] == '5') {
+ block_copy();
+ return;
+ }
+
+ setuserfile(fp_tmpbuf, tmpfname);
+ if (dashf(fp_tmpbuf)) {
+ more(fp_tmpbuf, NA);
+ getdata(b_lines - 1, 0, "¼È¦sÀɤw¦³¸ê®Æ (A)ªþ¥[ (W)Âмg (Q)¨ú®ø¡H[W] ", mode, sizeof(mode), LCECHO);
+ if (mode[0] == 'q')
+ goto cancel_block;
+ else if (mode[0] != 'a')
+ mode[0] = 'w';
+ }
+
+ if (getans("§R°£°Ï¶ô(Y/N)?[N] ") != 'y')
+ goto cancel_block;
+
+ block_save_to_file(tmpfname, mode[0] == 'a' ? BLOCK_APPEND : BLOCK_TRUNCATE);
+
+cancel_block:
+ curr_buf->blockln = -1;
+ curr_buf->redraw_everything = YEA;
+}
+
+static void
+block_select(void)
+{
+ if (has_block_selection()) {
+ block_prompt();
+ return;
+ }
+ curr_buf->blockln = curr_buf->currln;
+ curr_buf->blockpnt = curr_buf->currpnt;
+ curr_buf->blockline = curr_buf->currline;
+}
+
+static void
+block_shift_left()
+{
+ textline_t *p, *end;
+
+ setup_block_begin_end(&p, &end);
+
+ while (1) {
+ if (p->len) {
+ raw_shift_left(p->data, p->len);
+ --p->len;
+ }
+ if (p == end)
+ break;
+ else
+ p = p->next;
+ }
+ if (curr_buf->currpnt > curr_buf->currline->len)
+ curr_buf->currpnt = curr_buf->currline->len;
+ curr_buf->redraw_everything = YEA;
+}
+
+/**
+ * Shift the selected block right. If insert_mode is on, put a ' ' in each
+ * new place, otherwise, put insert_c instead.
+ */
+static void
+block_shift_right()
+{
+ textline_t *p, *end;
+
+ setup_block_begin_end(&p, &end);
+
+ while (1) {
+ if (p->len < WRAPMARGIN) {
+ raw_shift_right(p->data, ++p->len);
+ p->data[0] = curr_buf->insert_mode ? ' ' : curr_buf->insert_c;
+ }
+ if (p == end)
+ break;
+ else
+ p = p->next;
+ }
+ if (curr_buf->currpnt > curr_buf->currline->len)
+ curr_buf->currpnt = curr_buf->currline->len;
+ curr_buf->redraw_everything = YEA;
+}
+
+static inline void
+display_textline_internal(textline_t *p, int i, int min, int max)
+{
+ char inblock;
+ short tmp;
+ void (*output)(const char *);
+ void (*output_n)(const char *, int);
+
+ move(i, 0);
+ clrtoeol();
+
+ if (!p) {
+ outc('~');
+ return;
+ }
+
+ if (curr_buf->ansimode) {
+ output = outs;
+ output_n = outs_n;
+ }
+ else {
+ output = edit_outs;
+ output_n = edit_outs_n;
+ }
+
+ tmp = curr_buf->currln - curr_buf->curr_window_line + i;
+
+ /* if line 'i' is in block's range */
+ if (has_block_selection() && (
+ (curr_buf->blockln <= curr_buf->currln &&
+ curr_buf->blockln <= tmp && tmp <= curr_buf->currln) ||
+ (curr_buf->currln <= tmp && tmp <= curr_buf->blockln)) ) {
+ outs("\033[7m");
+ inblock = 1;
+ } else
+ inblock = 0;
+
+ if (curr_buf->currln == curr_buf->blockln && p == curr_buf->currline && max > min) {
+ outs("\033[m");
+ (*output_n)(p->data, min);
+ outs("\033[7m");
+ (*output_n)(p->data + min, max - min);
+ outs("\033[m");
+ (*output)(p->data + max);
+ } else
+ (*output)((curr_buf->edit_margin < p->len) ? &p->data[curr_buf->edit_margin] : "");
+
+ if (inblock)
+ outs("\033[m");
+}
+/**
+ * given a textline_t 'text' and the line number 'n' in the content,
+ * display this line.
+ */
+static void
+display_textline(textline_t *text, int n)
+{
+ short begin, end;
+
+ setup_block_begin_end_number(&begin, &end);
+ display_textline_internal(text, n, begin, end);
+}
+
+static void
+refresh_window(void)
+{
+ register textline_t *p;
+ register int i;
+ short begin, end;
+
+ setup_block_begin_end_number(&begin, &end);
for (p = curr_buf->top_of_win, i = 0; i < b_lines; i++) {
- move(i, 0);
- clrtoeol();
- if (curr_buf->blockln >= 0 &&
- ((curr_buf->blockln <= curr_buf->currln && curr_buf->blockln <= (curr_buf->currln - curr_buf->curr_window_line + i) &&
- (curr_buf->currln - curr_buf->curr_window_line + i) <= curr_buf->currln) ||
- (curr_buf->currln <= (curr_buf->currln - curr_buf->curr_window_line + i) &&
- (curr_buf->currln - curr_buf->curr_window_line + i) <= curr_buf->blockln))) {
- outs("\033[7m");
- inblock = 1;
- } else
- inblock = 0;
- if (p) {
- if (curr_buf->my_ansimode)
- if (curr_buf->currln == curr_buf->blockln && p == curr_buf->currline && max > min) {
- outs("\033[m");
- strncpy(buf, p->data, min);
- buf[min] = 0;
- outs(buf);
- outs("\033[7m");
- strncpy(buf, p->data + min, max - min);
- buf[max - min] = 0;
- outs(buf);
- outs("\033[m");
- outs(p->data + max);
- } else
- outs(p->data);
- else if (curr_buf->currln == curr_buf->blockln && p == curr_buf->currline && max > min) {
- outs("\033[m");
- strncpy(buf, p->data, min);
- buf[min] = 0;
- edit_outs(buf);
- outs("\033[7m");
- strncpy(buf, p->data + min, max - min);
- buf[max - min] = 0;
- edit_outs(buf);
- outs("\033[m");
- edit_outs(p->data + max);
- } else
- edit_outs((curr_buf->edit_margin < p->len) ? &p->data[curr_buf->edit_margin] : "");
+ display_textline_internal(p, i, begin, end);
+
+ if (p)
p = p->next;
- if (inblock)
- outs("\033[m");
- } else
- outc('~');
}
edit_msg();
}
@@ -1286,11 +1904,7 @@ display_buffer()
static void
goto_line(int lino)
{
- char buf[10];
-
- if (lino > 0 ||
- (getdata(b_lines - 1, 0, "¸õ¦Ü²Ä´X¦æ:", buf, sizeof(buf), DOECHO) &&
- sscanf(buf, "%d", &lino) && lino > 0)) {
+ if (lino > 0 && lino <= curr_buf->totaln + 1) {
textline_t *p;
p = curr_buf->firstline;
@@ -1305,14 +1919,16 @@ goto_line(int lino)
curr_buf->currln = curr_buf->totaln;
curr_buf->currline = curr_buf->lastline;
}
+
curr_buf->currpnt = 0;
- if (curr_buf->currln < 11) {
+
+ /* move window */
+ if (curr_buf->currln < middle_line()) {
curr_buf->top_of_win = curr_buf->firstline;
curr_buf->curr_window_line = curr_buf->currln;
} else {
- int i;
-
- curr_buf->curr_window_line = 11;
+ int i;
+ curr_buf->curr_window_line = middle_line();
for (i = curr_buf->curr_window_line; i; i--)
p = p->prev;
curr_buf->top_of_win = p;
@@ -1321,26 +1937,46 @@ goto_line(int lino)
curr_buf->redraw_everything = YEA;
}
-/*
- * mode: 0: prompt 1: forward -1: backward
+static void
+prompt_goto_line()
+{
+ char buf[10];
+
+ if (getdata(b_lines - 1, 0, "¸õ¦Ü²Ä´X¦æ:", buf, sizeof(buf), DOECHO))
+ goto_line(atoi(buf));
+}
+
+/**
+ * search string interactively.
+ * @param mode 0: prompt
+ * 1: forward
+ * -1: backward
*/
static void
search_str(int mode)
{
- static char str[65];
- typedef char *(*FPTR) ();
- static FPTR fptr;
+ const int max_keyword = 65;
+ char *str;
char ans[4] = "n";
+ if (curr_buf->searched_string == NULL) {
+ if (mode != 0)
+ return;
+ curr_buf->searched_string = (char *)malloc(max_keyword * sizeof(char));
+ curr_buf->searched_string[0] = 0;
+ }
+
+ str = curr_buf->searched_string;
+
if (!mode) {
if (getdata_buf(b_lines - 1, 0, "[·j´M]ÃöÁä¦r:",
- str, sizeof(str), DOECHO))
+ str, max_keyword, DOECHO))
if (*str) {
if (getdata(b_lines - 1, 0, "°Ï¤À¤j¤p¼g(Y/N/Q)? [N] ",
ans, sizeof(ans), LCECHO) && *ans == 'y')
- fptr = strstr;
+ curr_buf->substr_fp = strstr;
else
- fptr = strcasestr;
+ curr_buf->substr_fp = strcasestr;
}
}
if (*str && *ans != 'q') {
@@ -1350,27 +1986,28 @@ search_str(int mode)
if (mode >= 0) {
for (lino = curr_buf->currln, p = curr_buf->currline; p; p = p->next, lino++)
- if ((pos = fptr(p->data + (lino == curr_buf->currln ? curr_buf->currpnt + 1 : 0),
+ if ((pos = (*curr_buf->substr_fp)(p->data + (lino == curr_buf->currln ? curr_buf->currpnt + 1 : 0),
str)) && (lino != curr_buf->currln ||
pos - p->data != curr_buf->currpnt))
break;
} else {
for (lino = curr_buf->currln, p = curr_buf->currline; p; p = p->prev, lino--)
- if ((pos = fptr(p->data, str)) &&
+ if ((pos = (*curr_buf->substr_fp)(p->data, str)) &&
(lino != curr_buf->currln || pos - p->data != curr_buf->currpnt))
break;
}
if (pos) {
+ /* move window */
curr_buf->currline = p;
curr_buf->currln = lino;
curr_buf->currpnt = pos - p->data;
- if (lino < 11) {
+ if (lino < middle_line()) {
curr_buf->top_of_win = curr_buf->firstline;
curr_buf->curr_window_line = curr_buf->currln;
} else {
int i;
- curr_buf->curr_window_line = 11;
+ curr_buf->curr_window_line = middle_line();
for (i = curr_buf->curr_window_line; i; i--)
p = p->prev;
curr_buf->top_of_win = p;
@@ -1382,6 +2019,9 @@ search_str(int mode)
curr_buf->redraw_everything = YEA;
}
+/**
+ * move the cursor from bracket to corresponding bracket.
+ */
static void
match_paren()
{
@@ -1400,6 +2040,7 @@ match_paren()
parenum = ((ptype - parens) % 2) ? -1 : 1;
/* FIXME CRASH */
+ /* FIXME refactoring */
if (parenum > 0) {
for (lino = curr_buf->currln, p = curr_buf->currline; p; p = p->next, lino++) {
int len = strlen(p->data);
@@ -1499,13 +2140,13 @@ p_outscan:
curr_buf->currln = lino;
if (lino < top || lino > bottom) {
- if (lino < 11) {
+ if (lino < middle_line()) {
curr_buf->top_of_win = curr_buf->firstline;
curr_buf->curr_window_line = curr_buf->currln;
} else {
int i;
- curr_buf->curr_window_line = 11;
+ curr_buf->curr_window_line = middle_line();
for (i = curr_buf->curr_window_line; i; i--)
p = p->prev;
curr_buf->top_of_win = p;
@@ -1516,197 +2157,78 @@ p_outscan:
}
static void
-block_del(int hide)
+currline_shift_left(void)
{
- if (curr_buf->blockln < 0) {
- curr_buf->blockln = curr_buf->currln;
- curr_buf->blockpnt = curr_buf->currpnt;
- curr_buf->blockline = curr_buf->currline;
- } else {
- char fp_tmpbuf[80];
- FILE *fp;
- textline_t *begin, *end, *p;
- char tmpfname[10] = "buf.0";
- char ans[6] = "w+n";
+ int currpnt0;
- move(b_lines - 1, 0);
- clrtoeol();
- if (hide == 1)
- tmpfname[4] = 'q';
- else if (!hide && !getdata(b_lines - 1, 0, "§â°Ï¶ô²¾¦Ü¼È¦sÀÉ "
- "(0:Cut, 5:Copy, 6-9, q: Cancel)[0] ",
- tmpfname + 4, 4, LCECHO))
- tmpfname[4] = '0';
- if (tmpfname[4] < '0' || tmpfname[4] > '9')
- tmpfname[4] = 'q';
- if ('1' <= tmpfname[4] && tmpfname[4] <= '9') {
- setuserfile(fp_tmpbuf, tmpfname);
- if (tmpfname[4] != '5' && dashf(fp_tmpbuf)) {
- more(fp_tmpbuf, NA);
- getdata(b_lines - 1, 0, "¼È¦sÀɤw¦³¸ê®Æ (A)ªþ¥[ (W)Âмg "
- "(Q)¨ú®ø¡H[W] ", ans, 2, LCECHO);
- if (*ans == 'q')
- tmpfname[4] = 'q';
- else if (*ans != 'a')
- *ans = 'w';
- }
- if (tmpfname[4] != '5') {
- getdata(b_lines - 1, 0, "§R°£°Ï¶ô(Y/N)?[N] ",
- ans + 2, 4, LCECHO);
- if (ans[2] != 'y')
- ans[2] = 'n';
- }
- } else if (hide != 3)
- ans[2] = 'y';
-
- tmpfname[5] = ans[1] = ans[3] = 0;
- if (tmpfname[4] != 'q') {
- if (curr_buf->currln >= curr_buf->blockln) {
- begin = curr_buf->blockline;
- end = curr_buf->currline;
- if (ans[2] == 'y' && !(begin == end && curr_buf->currpnt != curr_buf->blockpnt)) {
- curr_buf->curr_window_line -= (curr_buf->currln - curr_buf->blockln);
- if (curr_buf->curr_window_line < 0) {
- curr_buf->curr_window_line = 0;
- if (end->next)
- (curr_buf->top_of_win = end->next)->prev = begin->prev;
- else
- curr_buf->top_of_win = (curr_buf->lastline = begin->prev);
- }
- curr_buf->currln -= (curr_buf->currln - curr_buf->blockln);
- }
- } else {
- begin = curr_buf->currline;
- end = curr_buf->blockline;
- }
- if (ans[2] == 'y' && !(begin == end && curr_buf->currpnt != curr_buf->blockpnt)) {
- if (begin->prev)
- begin->prev->next = end->next;
- else if (end->next)
- curr_buf->top_of_win = curr_buf->firstline = end->next;
- else {
- curr_buf->currline = curr_buf->top_of_win = curr_buf->firstline =
- curr_buf->lastline = alloc_line(WRAPMARGIN);
- curr_buf->currln = curr_buf->curr_window_line = curr_buf->edit_margin = 0;
- }
+ if (curr_buf->currline->len <= 0)
+ return;
- if (end->next)
- (curr_buf->currline = end->next)->prev = begin->prev;
- else if (begin->prev) {
- curr_buf->currline = (curr_buf->lastline = begin->prev);
- curr_buf->currln--;
- if (curr_buf->curr_window_line > 0)
- curr_buf->curr_window_line--;
- }
- }
- setuserfile(fp_tmpbuf, tmpfname);
- if ((fp = fopen(fp_tmpbuf, ans))) {
- if (begin == end && curr_buf->currpnt != curr_buf->blockpnt) {
- char buf[WRAPMARGIN + 2];
-
- if (curr_buf->currpnt > curr_buf->blockpnt) {
- strlcpy(buf, begin->data + curr_buf->blockpnt, sizeof(buf));
- buf[curr_buf->currpnt - curr_buf->blockpnt] = 0;
- } else {
- strlcpy(buf, begin->data + curr_buf->currpnt, sizeof(buf));
- buf[curr_buf->blockpnt - curr_buf->currpnt] = 0;
- }
- fputs(buf, fp);
- } else {
- for (p = begin; p != end; p = p->next)
- fprintf(fp, "%s\n", p->data);
- fprintf(fp, "%s\n", end->data);
- }
- fclose(fp);
- }
- if (ans[2] == 'y') {
- if (begin == end && curr_buf->currpnt != curr_buf->blockpnt) {
- int min, max;
-
- if (curr_buf->currpnt > curr_buf->blockpnt) {
- min = curr_buf->blockpnt;
- max = curr_buf->currpnt;
- } else {
- min = curr_buf->currpnt;
- max = curr_buf->blockpnt;
- }
- strlcpy(begin->data + min, begin->data + max, sizeof(begin->data) - min);
- begin->len -= max - min;
- curr_buf->currpnt = min;
- } else {
- for (p = begin; p != end; curr_buf->totaln--)
- free((p = p->next)->prev);
- free(end);
- curr_buf->totaln--;
- curr_buf->currpnt = 0;
- }
- }
- }
- curr_buf->blockln = -1;
- curr_buf->redraw_everything = YEA;
- }
+ currpnt0 = curr_buf->currpnt;
+ curr_buf->currpnt = 0;
+ delete_char();
+ curr_buf->currpnt = (currpnt0 <= curr_buf->currline->len) ? currpnt0 : currpnt0 - 1;
+ if (curr_buf->ansimode)
+ curr_buf->currpnt = ansi2n(n2ansi(curr_buf->currpnt, curr_buf->currline), curr_buf->currline);
}
static void
-block_shift_left()
+currline_shift_right(void)
{
- textline_t *begin, *end, *p;
+ int currpnt0;
- if (curr_buf->currln >= curr_buf->blockln) {
- begin = curr_buf->blockline;
- end = curr_buf->currline;
- } else {
- begin = curr_buf->currline;
- end = curr_buf->blockline;
- }
- p = begin;
- while (1) {
- if (p->len) {
- strcpy(p->data, p->data + 1);
- --p->len;
- }
- if (p == end)
- break;
- else
- p = p->next;
- }
- if (curr_buf->currpnt > curr_buf->currline->len)
- curr_buf->currpnt = curr_buf->currline->len;
- curr_buf->redraw_everything = YEA;
+ if (curr_buf->currline->len >= WRAPMARGIN - 1)
+ return;
+
+ currpnt0 = curr_buf->currpnt;
+ curr_buf->currpnt = 0;
+ insert_char(' ');
+ curr_buf->currpnt = currpnt0;
}
static void
-block_shift_right()
+cursor_to_next_word(void)
{
- textline_t *begin, *end, *p;
+ while (curr_buf->currpnt < curr_buf->currline->len &&
+ isalnum((int)curr_buf->currline->data[++curr_buf->currpnt]));
+ while (curr_buf->currpnt < curr_buf->currline->len &&
+ isspace((int)curr_buf->currline->data[++curr_buf->currpnt]));
+}
- if (curr_buf->currln >= curr_buf->blockln) {
- begin = curr_buf->blockline;
- end = curr_buf->currline;
- } else {
- begin = curr_buf->currline;
- end = curr_buf->blockline;
- }
- p = begin;
- while (1) {
- if (p->len < WRAPMARGIN) {
- int i = p->len + 1;
+static void
+cursor_to_prev_word(void)
+{
+ while (curr_buf->currpnt && isspace((int)curr_buf->currline->data[--curr_buf->currpnt]));
+ while (curr_buf->currpnt && isalnum((int)curr_buf->currline->data[--curr_buf->currpnt]));
+ if (curr_buf->currpnt > 0)
+ curr_buf->currpnt++;
+}
- while (i--)
- p->data[i + 1] = p->data[i];
- p->data[0] = curr_buf->insert_character ? ' ' : curr_buf->insert_c;
- ++p->len;
- }
- if (p == end)
+static inline int
+cursor_at_bottom_line(void)
+{
+ return curr_buf->curr_window_line == b_lines ||
+ (curr_buf->phone_mode && curr_buf->curr_window_line == b_lines - 1);
+}
+
+static void
+delete_current_word(void)
+{
+ while (curr_buf->currpnt < curr_buf->currline->len) {
+ delete_char();
+ if (!isalnum((int)curr_buf->currline->data[curr_buf->currpnt]))
+ break;
+ }
+ while (curr_buf->currpnt < curr_buf->currline->len) {
+ delete_char();
+ if (!isspace((int)curr_buf->currline->data[curr_buf->currpnt]))
break;
- else
- p = p->next;
}
- if (curr_buf->currpnt > curr_buf->currline->len)
- curr_buf->currpnt = curr_buf->currline->len;
- curr_buf->redraw_everything = YEA;
}
+/**
+ * transform every "*[" in given string to KEY_ESC "["
+ */
static void
transform_to_color(char *line)
{
@@ -1723,13 +2245,8 @@ block_color()
{
textline_t *begin, *end, *p;
- if (curr_buf->currln >= curr_buf->blockln) {
- begin = curr_buf->blockline;
- end = curr_buf->currline;
- } else {
- begin = curr_buf->currline;
- end = curr_buf->blockline;
- }
+ setup_block_begin_end(&begin, &end);
+
p = begin;
while (1) {
transform_to_color(p->data);
@@ -1738,39 +2255,181 @@ block_color()
else
p = p->next;
}
- block_del(1);
+ block_cancel();
}
-static char*
-phone_char(char c)
+/**
+ * insert ansi code
+ */
+static void
+insert_ansi_code(void)
+{
+ int ch = curr_buf->insert_mode;
+ curr_buf->insert_mode = curr_buf->redraw_everything = YEA;
+ if (!curr_buf->ansimode)
+ insert_string(reset_color);
+ else {
+ char ans[4];
+ move(b_lines - 2, 55);
+ outs("\033[1;33;40mB\033[41mR\033[42mG\033[43mY\033[44mL"
+ "\033[45mP\033[46mC\033[47mW\033[m");
+ if (getdata(b_lines - 1, 0,
+ "½Ð¿é¤J «G«×/«e´º/­I´º[¥¿±`¥Õ¦r¶Â©³][0wb]¡G",
+ ans, sizeof(ans), LCECHO))
+ {
+ const char t[] = "BRGYLPCW";
+ char color[15];
+ char *tmp, *apos = ans;
+ int fg, bg;
+
+ strcpy(color, "\033[");
+ if (isdigit((int)*apos)) {
+ sprintf(color,"%s%c", color, *(apos++));
+ if (*apos)
+ strcat(color, ";");
+ }
+ if (*apos) {
+ if ((tmp = strchr(t, toupper(*(apos++)))))
+ fg = tmp - t + 30;
+ else
+ fg = 37;
+ sprintf(color, "%s%d", color, fg);
+ }
+ if (*apos) {
+ if ((tmp = strchr(t, toupper(*(apos++)))))
+ bg = tmp - t + 40;
+ else
+ bg = 40;
+ sprintf(color, "%s;%d", color, bg);
+ }
+ strcat(color, "m");
+ insert_string(color);
+ } else
+ insert_string(reset_color);
+ }
+ curr_buf->insert_mode = ch;
+}
+
+static inline void
+phone_mode_switch(void)
{
+ if (curr_buf->phone_mode)
+ curr_buf->phone_mode = 0;
+ else {
+ curr_buf->phone_mode = 1;
+ if (!curr_buf->last_phone_mode)
+ curr_buf->last_phone_mode = 2;
+ }
+}
- if (curr_buf->phone_mode > 0 && curr_buf->phone_mode < 20) {
- if (tolower(c)<'a'||(tolower(c)-'a') >= strlen(BIG5[curr_buf->phone_mode - 1]) / 2)
+/**
+ * return coresponding phone char of given key c
+ */
+static const char*
+phone_char(char c)
+{
+ if (curr_buf->last_phone_mode > 0 && curr_buf->last_phone_mode < 20) {
+ if (tolower(c)<'a'||(tolower(c)-'a') >= strlen(BIG5[curr_buf->last_phone_mode - 1]) / 2)
return 0;
- return BIG5[curr_buf->phone_mode - 1] + (tolower(c) - 'a') * 2;
+ return BIG5[curr_buf->last_phone_mode - 1] + (tolower(c) - 'a') * 2;
}
- else if (curr_buf->phone_mode >= 20) {
+ else if (curr_buf->last_phone_mode >= 20) {
if (c == '.') c = '/';
if (c < '/' || c > '9')
return 0;
- return table[curr_buf->phone_mode - 20] + (c - '/') * 2;
+ return table[curr_buf->last_phone_mode - 20] + (c - '/') * 2;
}
return 0;
}
+/**
+ * When get the key for phone mode, handle it (e.g. edit_msg) and return the
+ * key. Otherwise return 0.
+ */
+static inline char
+phone_mode_filter(char ch)
+{
+ if (!curr_buf->phone_mode)
+ return 0;
+
+ switch (ch) {
+ case 'z':
+ case 'Z':
+ if (curr_buf->last_phone_mode < 20)
+ curr_buf->last_phone_mode = 20;
+ else
+ curr_buf->last_phone_mode = 2;
+ edit_msg();
+ return ch;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (curr_buf->last_phone_mode < 20) {
+ curr_buf->last_phone_mode = ch - '0' + 1;
+ curr_buf->redraw_everything = YEA;
+ return ch;
+ }
+ break;
+ case '-':
+ if (curr_buf->last_phone_mode < 20) {
+ curr_buf->last_phone_mode = 11;
+ curr_buf->redraw_everything = YEA;
+ return ch;
+ }
+ break;
+ case '=':
+ if (curr_buf->last_phone_mode < 20) {
+ curr_buf->last_phone_mode = 12;
+ curr_buf->redraw_everything = YEA;
+ return ch;
+ }
+ break;
+ case '`':
+ if (curr_buf->last_phone_mode < 20) {
+ curr_buf->last_phone_mode = 13;
+ curr_buf->redraw_everything = YEA;
+ return ch;
+ }
+ break;
+ case '/':
+ if (curr_buf->last_phone_mode >= 20) {
+ curr_buf->last_phone_mode += 4;
+ if (curr_buf->last_phone_mode > 27)
+ curr_buf->last_phone_mode -= 8;
+ curr_buf->redraw_everything = YEA;
+ return ch;
+ }
+ break;
+ case '*':
+ if (curr_buf->last_phone_mode >= 20) {
+ curr_buf->last_phone_mode++;
+ if ((curr_buf->last_phone_mode - 21) % 4 == 3)
+ curr_buf->last_phone_mode -= 4;
+ curr_buf->redraw_everything = YEA;
+ return ch;
+ }
+ break;
+ }
+
+ return 0;
+}
/* ½s¿è³B²z¡G¥Dµ{¦¡¡BÁä½L³B²z */
int
vedit(char *fpath, int saveheader, int *islocal)
{
- FILE *fp1;
- char last = 0, *pstr; /* the last key you press */
+ char last = 0; /* the last key you press */
int ch, ret;
- int lastindent = -1;
- int last_margin;
+
int mode0 = currutmp->mode;
int destuid0 = currutmp->destuid;
int money = 0;
@@ -1783,7 +2442,6 @@ vedit(char *fpath, int saveheader, int *islocal)
currutmp->destuid = currstat;
enter_edit_buffer();
- init_edit_buffer(curr_buf);
oldcurrline = curr_buf->currline = curr_buf->top_of_win =
curr_buf->firstline = curr_buf->lastline = alloc_line(WRAPMARGIN);
@@ -1794,31 +2452,36 @@ vedit(char *fpath, int saveheader, int *islocal)
if (*quote_file) {
do_quote();
*quote_file = '\0';
+ // FIXME it's never used ??
if (quote_file[79] == 'L')
local_article = 1;
}
- // No matter you quote or not, just start from (0,0)
+ /* No matter you quote or not, just start the cursor from (0,0) */
curr_buf->currline = curr_buf->firstline;
- curr_buf->currpnt = curr_buf->currln = curr_buf->curr_window_line = curr_buf->edit_margin = last_margin = 0;
+ curr_buf->currpnt = curr_buf->currln = curr_buf->curr_window_line = curr_buf->edit_margin = curr_buf->last_margin = 0;
while (1) {
- if (curr_buf->redraw_everything || curr_buf->blockln >= 0) {
- display_buffer();
+ if (curr_buf->redraw_everything || has_block_selection()) {
+ refresh_window();
curr_buf->redraw_everything = NA;
}
if( oldcurrline != curr_buf->currline ){
oldcurrline = adjustline(oldcurrline, oldcurrline->len);
oldcurrline = curr_buf->currline = adjustline(curr_buf->currline, WRAPMARGIN);
}
- if (curr_buf->my_ansimode)
+
+ if (curr_buf->ansimode)
ch = n2ansi(curr_buf->currpnt, curr_buf->currline);
else
ch = curr_buf->currpnt - curr_buf->edit_margin;
move(curr_buf->curr_window_line, ch);
- // XXX dont strcmp, just do it ?
+
+#if 0 // DEPRECATED, it's really not a well known expensive feature
if (!curr_buf->line_dirty && strcmp(editline, curr_buf->currline->data))
strcpy(editline, curr_buf->currline->data);
+#endif
+
ch = igetch();
/* jochang debug */
if ((interval = (now - th))) {
@@ -1838,7 +2501,7 @@ vedit(char *fpath, int saveheader, int *islocal)
/*
log_file("etc/illegal_money", LOG_CREAT | LOG_VF,
"\033[1;33;46m%s \033[37;45m ¥Î¾÷¾¹¤Hµoªí¤å³¹ \033[37m %s\033[m\n",
- cuser.userid, ctime4(&now));
+ cuser.userid, ctime(&now));
post_violatelaw(cuser.userid, "Ptt¨t²Îĵ¹î",
"¥Î¾÷¾¹¤Hµoªí¤å³¹", "±j¨îÂ÷¯¸");
abort_bbs(0);
@@ -1857,94 +2520,23 @@ vedit(char *fpath, int saveheader, int *islocal)
continue;
}
}
- if (curr_buf->phone_mode) {
- switch (ch) {
- case 'z':
- case 'Z':
- if (curr_buf->phone_mode < 20)
- curr_buf->phone_mode = curr_buf->phone_mode0 = 20;
- else
- curr_buf->phone_mode = curr_buf->phone_mode0 = 2;
- curr_buf->line_dirty = 1;
- curr_buf->redraw_everything = YEA;
- continue;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (curr_buf->phone_mode < 20) {
- curr_buf->phone_mode = curr_buf->phone_mode0 = ch - '0' + 1;
- curr_buf->line_dirty = 1;
- curr_buf->redraw_everything = YEA;
- continue;
- }
- break;
- case '-':
- if (curr_buf->phone_mode < 20) {
- curr_buf->phone_mode = curr_buf->phone_mode0 = 11;
- curr_buf->line_dirty = 1;
- curr_buf->redraw_everything = YEA;
- continue;
- }
- break;
- case '=':
- if (curr_buf->phone_mode < 20) {
- curr_buf->phone_mode = curr_buf->phone_mode0 = 12;
- curr_buf->line_dirty = 1;
- curr_buf->redraw_everything = YEA;
- continue;
- }
- break;
- case '`':
- if (curr_buf->phone_mode < 20) {
- curr_buf->phone_mode = curr_buf->phone_mode0 = 13;
- curr_buf->line_dirty = 1;
- curr_buf->redraw_everything = YEA;
- continue;
- }
- break;
- case '/':
- if (curr_buf->phone_mode >= 20) {
- curr_buf->phone_mode += 4;
- if (curr_buf->phone_mode > 27)
- curr_buf->phone_mode -= 8;
- curr_buf->line_dirty = 1;
- curr_buf->redraw_everything = YEA;
- continue;
- }
- break;
- case '*':
- if (curr_buf->phone_mode >= 20) {
- curr_buf->phone_mode++;
- if ((curr_buf->phone_mode - 21) % 4 == 3)
- curr_buf->phone_mode -= 4;
- curr_buf->line_dirty = 1;
- curr_buf->redraw_everything = YEA;
- continue;
- }
- break;
- }
- }
+
+ if (phone_mode_filter(ch))
+ continue;
if (ch < 0x100 && isprint2(ch)) {
+ const char *pstr;
if(curr_buf->phone_mode && (pstr=phone_char(ch)))
insert_dchar(pstr);
else
insert_char(ch);
- lastindent = -1;
- curr_buf->line_dirty = 1;
+ curr_buf->lastindent = -1;
} else {
if (ch == KEY_UP || ch == KEY_DOWN ){
- if (lastindent == -1)
- lastindent = curr_buf->currpnt;
+ if (curr_buf->lastindent == -1)
+ curr_buf->lastindent = curr_buf->currpnt;
} else
- lastindent = -1;
+ curr_buf->lastindent = -1;
if (ch == KEY_ESC)
switch (KEY_ESC_arg) {
case ',':
@@ -1969,9 +2561,11 @@ vedit(char *fpath, int saveheader, int *islocal)
case 'o':
ch = Ctrl('O');
break;
+#if 0 // DEPRECATED, it's really not a well known expensive feature
case '-':
ch = Ctrl('_');
break;
+#endif
case 's':
ch = Ctrl('S');
break;
@@ -1990,13 +2584,10 @@ vedit(char *fpath, int saveheader, int *islocal)
else
return ret;
}
- curr_buf->line_dirty = 1;
curr_buf->redraw_everything = YEA;
break;
case Ctrl('W'):
- if (curr_buf->blockln >= 0)
- block_del(2);
- curr_buf->line_dirty = 1;
+ block_cut();
break;
case Ctrl('Q'): /* Quit without saving */
ch = ask("µ²§ô¦ý¤£Àx¦s (Y/N)? [N]: ");
@@ -2006,67 +2597,20 @@ vedit(char *fpath, int saveheader, int *islocal)
exit_edit_buffer();
return -1;
}
- curr_buf->line_dirty = 1;
curr_buf->redraw_everything = YEA;
break;
case Ctrl('C'):
- ch = curr_buf->insert_character;
- curr_buf->insert_character = curr_buf->redraw_everything = YEA;
- if (!curr_buf->my_ansimode)
- insert_string(reset_color);
- else {
- char ans[4];
- move(b_lines - 2, 55);
- outs("\033[1;33;40mB\033[41mR\033[42mG\033[43mY\033[44mL"
- "\033[45mP\033[46mC\033[47mW\033[m");
- if (getdata(b_lines - 1, 0,
- "½Ð¿é¤J «G«×/«e´º/­I´º[¥¿±`¥Õ¦r¶Â©³][0wb]¡G",
- ans, sizeof(ans), LCECHO)) {
- char t[] = "BRGYLPCW";
- char color[15];
- char *tmp, *apos = ans;
- int fg, bg;
-
- strcpy(color, "\033[");
- if (isdigit((int)*apos)) {
- sprintf(color,"%s%c", color, *(apos++));
- if (*apos)
- strcat(color, ";");
- }
- if (*apos) {
- if ((tmp = strchr(t, toupper(*(apos++)))))
- fg = tmp - t + 30;
- else
- fg = 37;
- sprintf(color, "%s%d", color, fg);
- }
- if (*apos) {
- if ((tmp = strchr(t, toupper(*(apos++)))))
- bg = tmp - t + 40;
- else
- bg = 40;
- sprintf(color, "%s;%d", color, bg);
- }
- strcat(color, "m");
- insert_string(color);
- } else
- insert_string(reset_color);
- }
- curr_buf->insert_character = ch;
- curr_buf->line_dirty = 1;
+ insert_ansi_code();
break;
case KEY_ESC:
- curr_buf->line_dirty = 0;
switch (KEY_ESC_arg) {
case 'U':
t_users();
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 1;
break;
case 'i':
t_idle();
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 1;
break;
case 'n':
search_str(1);
@@ -2076,7 +2620,7 @@ vedit(char *fpath, int saveheader, int *islocal)
break;
case 'L':
case 'J':
- goto_line(0);
+ prompt_goto_line();
break;
case ']':
match_paren();
@@ -2096,87 +2640,51 @@ vedit(char *fpath, int saveheader, int *islocal)
break;
case 'l': /* block delete */
case ' ':
- block_del(0);
- curr_buf->line_dirty = 1;
+ block_select();
break;
case 'u':
- if (curr_buf->blockln >= 0)
- block_del(1);
- curr_buf->line_dirty = 1;
+ block_cancel();
break;
case 'c':
- if (curr_buf->blockln >= 0)
- block_del(3);
- curr_buf->line_dirty = 1;
+ block_copy();
break;
case 'y':
- undelete_line();
+ oldcurrline = undelete_line();
+ if (oldcurrline == NULL)
+ oldcurrline = curr_buf->currline;
break;
case 'R':
curr_buf->raw_mode ^= 1;
- curr_buf->line_dirty = 1;
break;
case 'I':
curr_buf->indent_mode ^= 1;
- curr_buf->line_dirty = 1;
break;
case 'j':
- if (curr_buf->blockln >= 0)
+ if (has_block_selection())
block_shift_left();
- else if (curr_buf->currline->len) {
- int currpnt0 = curr_buf->currpnt;
- curr_buf->currpnt = 0;
- delete_char();
- curr_buf->currpnt = (currpnt0 <= curr_buf->currline->len) ? currpnt0 :
- currpnt0 - 1;
- if (curr_buf->my_ansimode)
- curr_buf->currpnt = ansi2n(n2ansi(curr_buf->currpnt, curr_buf->currline),
- curr_buf->currline);
- }
- curr_buf->line_dirty = 1;
+ else
+ currline_shift_left();
break;
case 'k':
- if (curr_buf->blockln >= 0)
+ if (has_block_selection())
block_shift_right();
- else {
- int currpnt0 = curr_buf->currpnt;
-
- curr_buf->currpnt = 0;
- insert_char(' ');
- curr_buf->currpnt = currpnt0;
- }
- curr_buf->line_dirty = 1;
+ else
+ currline_shift_right();
break;
case 'f':
- while (curr_buf->currpnt < curr_buf->currline->len &&
- isalnum((int)curr_buf->currline->data[++curr_buf->currpnt]));
- while (curr_buf->currpnt < curr_buf->currline->len &&
- isspace((int)curr_buf->currline->data[++curr_buf->currpnt]));
- curr_buf->line_dirty = 1;
+ cursor_to_next_word();
break;
case 'b':
- while (curr_buf->currpnt && isalnum((int)curr_buf->currline->data[--curr_buf->currpnt]));
- while (curr_buf->currpnt && isspace((int)curr_buf->currline->data[--curr_buf->currpnt]));
- curr_buf->line_dirty = 1;
+ cursor_to_prev_word();
break;
case 'd':
- while (curr_buf->currpnt < curr_buf->currline->len) {
- delete_char();
- if (!isalnum((int)curr_buf->currline->data[curr_buf->currpnt]))
- break;
- }
- while (curr_buf->currpnt < curr_buf->currline->len) {
- delete_char();
- if (!isspace((int)curr_buf->currline->data[curr_buf->currpnt]))
- break;
- }
- curr_buf->line_dirty = 1;
+ delete_current_word();
break;
- default:
- curr_buf->line_dirty = 1;
}
break;
+#if 0 // DEPRECATED, it's really not a well known expensive feature
case Ctrl('_'):
+ // swap editline and currline's data
if (strcmp(editline, curr_buf->currline->data)) {
char buf[WRAPMARGIN];
@@ -2188,26 +2696,22 @@ vedit(char *fpath, int saveheader, int *islocal)
curr_buf->line_dirty = 1;
}
break;
+#endif
case Ctrl('S'):
search_str(0);
break;
case Ctrl('U'):
insert_char('\033');
- curr_buf->line_dirty = 1;
break;
case Ctrl('V'): /* Toggle ANSI color */
- curr_buf->my_ansimode ^= 1;
- if (curr_buf->my_ansimode && curr_buf->blockln >= 0)
+ curr_buf->ansimode ^= 1;
+ if (curr_buf->ansimode && has_block_selection())
block_color();
clear();
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 1;
break;
case Ctrl('I'):
- do {
- insert_char(' ');
- } while (curr_buf->currpnt & 0x7);
- curr_buf->line_dirty = 1;
+ insert_tab();
break;
case '\r':
case '\n':
@@ -2219,7 +2723,6 @@ vedit(char *fpath, int saveheader, int *islocal)
#endif
split(curr_buf->currline, curr_buf->currpnt);
oldcurrline = curr_buf->currline;
- curr_buf->line_dirty = 0;
break;
case Ctrl('G'):
{
@@ -2230,16 +2733,18 @@ vedit(char *fpath, int saveheader, int *islocal)
currstat = currstat0;
}
if (trans_buffer[0]) {
+ FILE *fp1;
if ((fp1 = fopen(trans_buffer, "r"))) {
- int indent_mode0 = curr_buf->indent_mode;
+ int indent_mode0 = curr_buf->indent_mode;
+ char buf[WRAPMARGIN + 2];
curr_buf->indent_mode = 0;
- while (fgets(editline, WRAPMARGIN + 2, fp1)) {
- if (!strncmp(editline, "§@ªÌ:", 5) ||
- !strncmp(editline, "¼ÐÃD:", 5) ||
- !strncmp(editline, "®É¶¡:", 5))
+ while (fgets(buf, sizeof(buf), fp1)) {
+ if (!strncmp(buf, "§@ªÌ:", 5) ||
+ !strncmp(buf, "¼ÐÃD:", 5) ||
+ !strncmp(buf, "®É¶¡:", 5))
continue;
- insert_string(editline);
+ insert_string(buf);
}
fclose(fp1);
curr_buf->indent_mode = indent_mode0;
@@ -2250,92 +2755,53 @@ vedit(char *fpath, int saveheader, int *islocal)
}
}
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 1;
break;
case Ctrl('P'):
- if (curr_buf->phone_mode)
- curr_buf->phone_mode = 0;
- else {
- if (curr_buf->phone_mode0)
- curr_buf->phone_mode = curr_buf->phone_mode0;
- else
- curr_buf->phone_mode = curr_buf->phone_mode0 = 2;
- }
+ phone_mode_switch();
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 1;
break;
case Ctrl('Z'): /* Help */
more("etc/ve.hlp", YEA);
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 1;
break;
case Ctrl('L'):
clear();
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 1;
break;
case KEY_LEFT:
if (curr_buf->currpnt) {
- if (curr_buf->my_ansimode)
+ if (curr_buf->ansimode)
curr_buf->currpnt = n2ansi(curr_buf->currpnt, curr_buf->currline);
curr_buf->currpnt--;
- if (curr_buf->my_ansimode)
+ if (curr_buf->ansimode)
curr_buf->currpnt = ansi2n(curr_buf->currpnt, curr_buf->currline);
- curr_buf->line_dirty = 1;
} else if (curr_buf->currline->prev) {
curr_buf->curr_window_line--;
curr_buf->currln--;
curr_buf->currline = curr_buf->currline->prev;
curr_buf->currpnt = curr_buf->currline->len;
- curr_buf->line_dirty = 0;
}
break;
case KEY_RIGHT:
if (curr_buf->currline->len != curr_buf->currpnt) {
- if (curr_buf->my_ansimode)
+ if (curr_buf->ansimode)
curr_buf->currpnt = n2ansi(curr_buf->currpnt, curr_buf->currline);
curr_buf->currpnt++;
- if (curr_buf->my_ansimode)
+ if (curr_buf->ansimode)
curr_buf->currpnt = ansi2n(curr_buf->currpnt, curr_buf->currline);
- curr_buf->line_dirty = 1;
} else if (curr_buf->currline->next) {
curr_buf->currpnt = 0;
curr_buf->curr_window_line++;
curr_buf->currln++;
curr_buf->currline = curr_buf->currline->next;
- curr_buf->line_dirty = 0;
}
break;
case KEY_UP:
- if (curr_buf->currline->prev) {
- if (curr_buf->my_ansimode)
- ch = n2ansi(curr_buf->currpnt, curr_buf->currline);
- curr_buf->curr_window_line--;
- curr_buf->currln--;
- curr_buf->currline = curr_buf->currline->prev;
- if (curr_buf->my_ansimode)
- curr_buf->currpnt = ansi2n(ch, curr_buf->currline);
- else
- curr_buf->currpnt = (curr_buf->currline->len > lastindent) ? lastindent :
- curr_buf->currline->len;
- curr_buf->line_dirty = 0;
- }
+ cursor_to_prev_line();
break;
case KEY_DOWN:
- if (curr_buf->currline->next) {
- if (curr_buf->my_ansimode)
- ch = n2ansi(curr_buf->currpnt, curr_buf->currline);
- curr_buf->currline = curr_buf->currline->next;
- curr_buf->curr_window_line++;
- curr_buf->currln++;
- if (curr_buf->my_ansimode)
- curr_buf->currpnt = ansi2n(ch, curr_buf->currline);
- else
- curr_buf->currpnt = (curr_buf->currline->len > lastindent) ? lastindent :
- curr_buf->currline->len;
- curr_buf->line_dirty = 0;
- }
+ cursor_to_next_line();
break;
case Ctrl('B'):
@@ -2344,11 +2810,10 @@ vedit(char *fpath, int saveheader, int *islocal)
curr_buf->top_of_win = back_line(curr_buf->top_of_win, 22);
curr_buf->currln = tmp;
curr_buf->currline = back_line(curr_buf->currline, 22);
- curr_buf->curr_window_line = getlineno();
+ curr_buf->curr_window_line = get_lineno_in_window();
if (curr_buf->currpnt > curr_buf->currline->len)
curr_buf->currpnt = curr_buf->currline->len;
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 0;
break;
}
@@ -2358,42 +2823,37 @@ vedit(char *fpath, int saveheader, int *islocal)
curr_buf->top_of_win = forward_line(curr_buf->top_of_win, 22);
curr_buf->currln = tmp;
curr_buf->currline = forward_line(curr_buf->currline, 22);
- curr_buf->curr_window_line = getlineno();
+ curr_buf->curr_window_line = get_lineno_in_window();
if (curr_buf->currpnt > curr_buf->currline->len)
curr_buf->currpnt = curr_buf->currline->len;
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 0;
break;
}
case KEY_END:
case Ctrl('E'):
curr_buf->currpnt = curr_buf->currline->len;
- curr_buf->line_dirty = 1;
break;
case Ctrl(']'): /* start of file */
curr_buf->currline = curr_buf->top_of_win = curr_buf->firstline;
curr_buf->currpnt = curr_buf->currln = curr_buf->curr_window_line = 0;
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 0;
break;
case Ctrl('T'): /* tail of file */
curr_buf->top_of_win = back_line(curr_buf->lastline, 23);
curr_buf->currline = curr_buf->lastline;
- curr_buf->curr_window_line = getlineno();
+ curr_buf->curr_window_line = get_lineno_in_window();
curr_buf->currln = curr_buf->totaln;
curr_buf->redraw_everything = YEA;
curr_buf->currpnt = 0;
- curr_buf->line_dirty = 0;
break;
case KEY_HOME:
case Ctrl('A'):
curr_buf->currpnt = 0;
- curr_buf->line_dirty = 1;
break;
case KEY_INS: /* Toggle insert/overwrite */
case Ctrl('O'):
- if (curr_buf->blockln >= 0 && curr_buf->insert_character) {
+ if (has_block_selection() && curr_buf->insert_mode) {
char ans[4];
getdata(b_lines - 1, 0,
@@ -2401,14 +2861,12 @@ vedit(char *fpath, int saveheader, int *islocal)
ans, sizeof(ans), LCECHO);
curr_buf->insert_c = ans[0] ? ans[0] : ' ';
}
- curr_buf->insert_character ^= 1;
- curr_buf->line_dirty = 1;
+ curr_buf->insert_mode ^= 1;
break;
case Ctrl('H'):
case '\177': /* backspace */
- curr_buf->line_dirty = 1;
- if (curr_buf->my_ansimode) {
- curr_buf->my_ansimode = 0;
+ if (curr_buf->ansimode) {
+ curr_buf->ansimode = 0;
clear();
curr_buf->redraw_everything = YEA;
} else {
@@ -2417,18 +2875,18 @@ vedit(char *fpath, int saveheader, int *islocal)
if (!curr_buf->currline->prev)
break;
- curr_buf->line_dirty = 0;
curr_buf->curr_window_line--;
curr_buf->currln--;
+
+ curr_buf->currline = adjustline(curr_buf->currline, curr_buf->currline->len);
curr_buf->currline = curr_buf->currline->prev;
curr_buf->currline = adjustline(curr_buf->currline, WRAPMARGIN);
- // FIXME dirty fix. would this cause memory leak?
oldcurrline = curr_buf->currline;
curr_buf->currpnt = curr_buf->currline->len;
curr_buf->redraw_everything = YEA;
- if (*killsp(curr_buf->currline->next->data) == '\0') {
+ if (*next_non_space_char(curr_buf->currline->next->data) == '\0') {
delete_line(curr_buf->currline->next);
break;
}
@@ -2448,7 +2906,6 @@ vedit(char *fpath, int saveheader, int *islocal)
break;
case Ctrl('D'):
case KEY_DEL: /* delete current character */
- curr_buf->line_dirty = 1;
if (curr_buf->currline->len == curr_buf->currpnt) {
textline_t *p = curr_buf->currline;
@@ -2459,11 +2916,10 @@ vedit(char *fpath, int saveheader, int *islocal)
abort_bbs(0);
}
}
- curr_buf->line_dirty = 0;
curr_buf->redraw_everything = YEA;
} else {
delete_char();
- if (curr_buf->my_ansimode)
+ if (curr_buf->ansimode)
curr_buf->currpnt = ansi2n(n2ansi(curr_buf->currpnt, curr_buf->currline), curr_buf->currline);
}
break;
@@ -2474,8 +2930,10 @@ vedit(char *fpath, int saveheader, int *islocal)
textline_t *p = curr_buf->currline->next;
if (!p) {
p = curr_buf->currline->prev;
- if (!p)
+ if (!p) {
+ curr_buf->currline->data[0] = 0;
break;
+ }
if (curr_buf->curr_window_line > 0) {
curr_buf->curr_window_line--;
curr_buf->currln--;
@@ -2483,14 +2941,16 @@ vedit(char *fpath, int saveheader, int *islocal)
}
if (curr_buf->currline == curr_buf->top_of_win)
curr_buf->top_of_win = p;
+
delete_line(curr_buf->currline);
+ set_deleted_line(curr_buf->currline);
curr_buf->currline = p;
+
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 0;
oldcurrline = curr_buf->currline = adjustline(curr_buf->currline, WRAPMARGIN);
break;
}
- if (curr_buf->currline->len == curr_buf->currpnt) {
+ else if (curr_buf->currline->len == curr_buf->currpnt) {
textline_t *p = curr_buf->currline;
while (!join(p)) {
@@ -2501,43 +2961,25 @@ vedit(char *fpath, int saveheader, int *islocal)
}
}
curr_buf->redraw_everything = YEA;
- curr_buf->line_dirty = 0;
break;
}
curr_buf->currline->len = curr_buf->currpnt;
curr_buf->currline->data[curr_buf->currpnt] = '\0';
- curr_buf->line_dirty = 1;
break;
}
+
if (curr_buf->currln < 0)
curr_buf->currln = 0;
- if (curr_buf->curr_window_line < 0) {
- curr_buf->curr_window_line = 0;
- if (!curr_buf->top_of_win->prev)
- indigestion(6);
- else {
- curr_buf->top_of_win = curr_buf->top_of_win->prev;
- rscroll();
- }
- }
- if (curr_buf->curr_window_line == b_lines ||
- (curr_buf->phone_mode && curr_buf->curr_window_line == b_lines - 1)) {
+
+ if (curr_buf->curr_window_line < 0)
+ window_scroll_down();
+ else if (cursor_at_bottom_line()) {
if(curr_buf->phone_mode)
- curr_buf->curr_window_line = t_lines - 3;
+ curr_buf->curr_window_line = b_lines - 2;
else
- curr_buf->curr_window_line = t_lines - 2;
+ curr_buf->curr_window_line = b_lines - 1;
- if (!curr_buf->top_of_win->next)
- indigestion(7);
- else {
- curr_buf->top_of_win = curr_buf->top_of_win->next;
- if(curr_buf->phone_mode)
- move(b_lines-1, 0);
- else
- move(b_lines, 0);
- clrtoeol();
- scroll();
- }
+ window_scroll_up();
}
}
if (curr_buf->currpnt < t_columns - 1)
@@ -2546,13 +2988,13 @@ vedit(char *fpath, int saveheader, int *islocal)
curr_buf->edit_margin = curr_buf->currpnt / (t_columns - 8) * (t_columns - 8);
if (!curr_buf->redraw_everything) {
- if (curr_buf->edit_margin != last_margin) {
- last_margin = curr_buf->edit_margin;
+ if (curr_buf->edit_margin != curr_buf->last_margin) {
+ curr_buf->last_margin = curr_buf->edit_margin;
curr_buf->redraw_everything = YEA;
} else {
move(curr_buf->curr_window_line, 0);
clrtoeol();
- if (curr_buf->my_ansimode)
+ if (curr_buf->ansimode)
outs(curr_buf->currline->data);
else
edit_outs(&curr_buf->currline->data[curr_buf->edit_margin]);
diff --git a/mbbsd/screen.c b/mbbsd/screen.c
index 3232b1af..49ff84a2 100644
--- a/mbbsd/screen.c
+++ b/mbbsd/screen.c
@@ -354,15 +354,27 @@ outc(unsigned char c)
#endif
}
-int
+/**
+ * Just like outs, but print out '*' instead of 27(decimal) in the given string.
+ *
+ * FIXME column could not start from 0
+ */
+void
edit_outs(const char *text)
{
register int column = 0;
register char ch;
while ((ch = *text++) && (++column < t_columns))
outc(ch == 27 ? '*' : ch);
+}
- return 0;
+void
+edit_outs_n(const char *text, int n)
+{
+ register int column = 0;
+ register char ch;
+ while ((ch = *text++) && n-- && (++column < t_columns))
+ outc(ch == 27 ? '*' : ch);
}
void
@@ -373,6 +385,14 @@ outs(const char *str)
}
}
+void
+outs_n(const char *str, int n)
+{
+ while (*str && n--) {
+ outc(*str++);
+ }
+}
+
/* Jaky */
void
out_lines(const char *str, int line)