home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
ddjmag
/
ddj8812.arc
/
TWP.ASC
< prev
Wrap
Text File
|
1988-12-31
|
19KB
|
746 lines
_C PROGRAMMING COLUMN_
by Al Stevens
[LISTING 1]
/* ------------ help.h -------------- */
void load_help(char *);
void display_help(void);
extern char *help_window;
#define set_help(s) help_window=s
[LISTING 2]
/* --------- help.c ----------- */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include "window.h"
#include "menu.h"
#include "entry.h"
#include "help.h"
#define MAXHELPS 25
static struct helps {
char hname [9];
int h, w;
long hptr;
} hps [MAXHELPS+1];
extern FIELD *fld;
extern MENU *mn;
static int hp = 0;
static FILE *helpfp;
static char hline [80];
char *help_window;
/* ----------- load the HELP! definition file ------------ */
void load_help(char *hn)
{
extern void (*helpfunc)(void);
extern int helpkey;
char *cp;
helpfunc = display_help;
helpkey = F1;
hp = 0;
if ((helpfp = fopen(hn, "r")) == NULL)
return;
if ((fgets(hline, 80, helpfp)) == NULL)
return;
while (1) {
if (hp == MAXHELPS)
break;
if (strncmp(hline, "<end>", 5) == 0)
break;
if (*hline != '<')
continue;
hps[hp].h = 2;
hps[hp].w = 23;
strncpy(hps[hp].hname, hline+1, 8);
hps[hp].hname[8] = '\0';
cp = strchr(hps[hp].hname, '>');
if (cp)
*cp = '\0';
hps[hp].hptr = ftell(helpfp);
if (fgets(hline, 80, helpfp) == NULL)
strcpy(hline, "<end>");
while (hline[0] != '<') {
hps[hp].h++;
hps[hp].w = max(hps[hp].w, strlen(hline)+2);
if (fgets(hline, 80, helpfp) == NULL)
strcpy(hline, "<end>");
}
hp++;
}
}
/* ---------- display the current help window ----------- */
void display_help()
{
int hx, hy, i, xx, yy, ch;
extern int helpkey, hsel;
char *save_help;
static int inhelp = 0;
extern struct wn wkw;
if (inhelp)
return;
inhelp++;
save_help = help_window;
if (fld != NULL)
help_window = fld->fhelp;
else if (mn != NULL)
help_window = (mn+hsel-1)->mshelp [wkw.wy-1];
if (help_window != NULL) {
for (ch = 0; ch < hp; ch++)
if (strcmp(help_window, hps[ch].hname) == 0)
break;
if (ch < hp) {
xx = wherex();
yy = wherey();
hidecursor();
hx = ((80-hps[ch].w) / 2)+1;
hy = ((25-hps[ch].h) / 2)+1;
establish_window(hx, hy,
hx+hps[ch].w-1, hy+hps[ch].h,
HELPFG, HELPBG, TRUE);
fseek(helpfp, hps[ch].hptr, 0);
for (i = 0; i < hps[ch].h-2; i++) {
gotoxy(2,2+i);
fgets(hline, 80, helpfp);
cprintf(hline);
}
gotoxy(2,2+i);
cprintf(" [Any key to return]");
hidecursor();
getkey();
delete_window();
if (mn == NULL || fld != NULL) {
textcolor(FIELDFG);
textbackground(FIELDBG);
gotoxy(xx, yy);
}
}
}
help_window = save_help;
--inhelp;
}
[LISTING 3]
<editor>
TINY WORD PROCESSOR (TWP) COMMANDS
-------Cursor Movement------ ---------Page Movement--------
arrows = move text cursor Ctrl-Home = Beginning of File
Ctrl-T = Top of Window Ctrl-End = End of File
Ctrl-B = Bottom of Window PgUp = Previous Page
Ctrl -> = Next Word PgDn = Next Page
Ctrl <- = Previous Word
Home = Beginning of Line ---------Editor Control-------
End = End of Line Alt-A = Auto Paragraph Reform
Shift-Tab = Back tab
--------Block Controls------ ---------Edit Commands--------
F2 = Form Paragraph Alt-Q or Esc = Done
F5 = Mark Block Beginning Ins = Insert Mode
F6 = Mark Block End Del = Delete Char
F3 = Move Block <-- = Rubout
F4 = Copy Block Ctrl-D = Delete Word
F8 = Delete Block Alt-D = Delete Line
F9 = Unmark Block F7 = Find
Alt-F7 = Find again
<load>
Load a new file into TWP,
replacing the existing file.
<save>
Save the file from the
edit buffer.
<merge>
Merge a file into the
edit buffer at the
line where the cursor
is pointed.
<new>
Clear the edit buffer
and create a new file.
<quit>
Exit from TWP, returning to DOS
<move>
Move the block to the
line where the cursor
points. This is an
insert move.
<copy>
Copy the block to the
line where the cursor
points. This is an
insert copy.
<delete>
Delete the block closing
the space it occupies.
<hide>
Turn off the block
markers.
<formpara>
Form a paragraph.
This makes a paragraph from
a marked block, or, if no
block is marked, to the next
blank or indented line.
<markbeg>
Mark the beginning line
of a block for move, copy,
delete, or paragraph.
<markend>
Mark the ending line
of a block for move, copy,
delete, or paragraph.
<find>
Find a specified string
in the edit buffer.
Move the cursor to the
location where the string
was found.
<findagn>
Find the next occurrence
of the string most recently
specified.
<auto>
Turn on/off the automatic
paragraph forming feature.
<insert>
Turn on/off the
character insert mode.
(insert/overstrike toggle)
<filename>
Enter the path and file name.
The path is optional but must
be fully qualified if entered.
<findstr>
Enter the string to be searched
by the Find command.
<end>
[LISTING 4]
/* --------- editshel.c ------------ */
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include <mem.h>
#include <alloc.h>
#include <ctype.h>
#include "window.h"
#include "menu.h"
#include "entry.h"
#include "editor.h"
#include "help.h"
int MAXLINES; /* maximum number of editor lines */
#define EDITWIDTH 78 /* length of an editor line */
#define BUFLEN (EDITWIDTH*MAXLINES)
/* --------- alt keys returned by getkey() --------- */
#define ALT_A 158
#define ALT_L 166
#define ALT_M 178
#define ALT_N 177
/* -------- configured advanced editor commands --------- */
#define FIND F7
#define FIND_AGAIN ALT_F7
#define LOAD_FILE ALT_L
#define SAVE_FILE ALT_S
#define MERGE_FILE ALT_M
#define NEW_FILE ALT_N
#define EDITOR_MENU F10
#define REFORM ALT_A
/* ---------- editor menu tables --------- */
static char *fselcs[] = {
"Load [Alt-L]",
"Save [Alt-S]",
"Merge [Alt-M]",
"New [Alt-N]",
"Quit [Alt-Q]",
NULL
};
static char *filehelp[] = {
"load",
"save",
"merge",
"new",
"quit"
};
static char *eselcs[] = {
"Move [F3]",
"Copy [F4]",
"Delete [F8]",
"Hide [F9]",
"Paragraph [F2]",
"Mark Beg [F5]",
"Mark End [F6]",
"Find [F7]",
"Find Again [Alt-F7]",
NULL
};
static char *edithelp[] = {
"move",
"copy",
"delete",
"hide",
"formpara",
"markbeg",
"markend",
"find",
"findagn",
};
static char *oselcs[] = {
"Auto Paragraph Reformat [Alt-A]",
"Insert [Ins]",
NULL
};
static char *opthelp[] = {
"auto",
"insert"
};
void fileedit(char *);
static int edit(int,int);
static void editmenu(int);
static int get_filename(char *, int);
static int write_file(void);
static int load_file(int,int);
static int save_file(int,int);
static int merge_file(int,int);
static int new_file(int,int);
static void editkeys(int);
static void statusline(void);
static int findstring(void);
static char *find(char *, unsigned);
static int read_file(char *, char *, int, int, int);
static int bufferok(char *);
static void notice(char *);
void (*edit_extend)(void);
static char fkeys[] = {LOAD_FILE,SAVE_FILE,
MERGE_FILE,NEW_FILE,QUIT};
static char forced[] = {MOVE_BLOCK,COPY_BLOCK,
DELETE_BLOCK,HIDE_BLOCK,
PARAGRAPH,BEGIN_BLOCK,
END_BLOCK,FIND,FIND_AGAIN};
static char options[] = {REFORM,INS};
static int (*ffuncs[])() =
{load_file,save_file,merge_file,new_file,edit};
static int (*efuncs[])() =
{edit,edit,edit,edit,edit,edit,edit,edit,edit};
static int (*ofuncs[])() =
{edit,edit,edit};
MENU emn [] = {
{"File", NULL, fselcs, filehelp, fkeys, ffuncs, 0},
{"Edit", NULL, eselcs, edithelp, forced, efuncs, 0},
{"Options", NULL, oselcs, opthelp, options, ofuncs, 0},
{NULL}
};
/* ------ filename data entry template and buffer ------- */
static char filename[65];
static char savefn [65];
static char filemask[65];
FIELD fn_template[] = {
{2,14,1,filename,filemask,"filename"},
{0}
};
/* ------- text find data entry template and buffer ------ */
static char findstr[71];
static char findmask[71];
FIELD find_template[] = {
{ 2,8,1,findstr,findmask,"findstr"},
{0}
};
extern int forcechar;
extern struct edit_env ev;
static void editkeys(int c)
{
switch(c) {
case REFORM:
ev.reforming ^= TRUE;
break;
case NEW_FILE:
new_file(1,1);
break;
case LOAD_FILE:
load_file(1,1);
break;
case SAVE_FILE:
save_file(1,1);
break;
case MERGE_FILE:
merge_file(1,1);
break;
case FIND:
if (!findstring())
break;
case FIND_AGAIN:
ev.nowptr++;
ev.nowptr = find(ev.nowptr, ev.lstptr-ev.nowptr);
if (ev.nowptr != NULL) {
ev.curr_x = (ev.nowptr-ev.topptr) % ev.wwd;
if (ev.nowptr >= ev.bfptr+ev.wwd*ev.wdo->ht)
ev.bfptr = ev.nowptr - ev.curr_x;
ev.curr_y = (ev.nowptr - ev.bfptr) / ev.wwd;
}
else
error_message("Not found ...");
break;
case ALT_F:
editmenu(1);
break;
case ALT_E:
editmenu(2);
break;
case ALT_O:
editmenu(3);
break;
case EDITOR_MENU:
editmenu(0);
break;
default:
if (edit_extend)
(*edit_extend)();
else
putch(BELL);
break;
}
}
static void editmenu(n)
{
menu_select(emn, n);
}
static int edit(hs,vs)
{
forcechar = emn[hs-1].mskeys[vs-1] & 255;
return TRUE;
}
/* ---------- edit a file -------------- */
void fileedit(char *file)
{
char *bf, *mb;
extern void (*editfunc)();
extern void (*status_line)();
setmem(filename, 64, ' ');
setmem(filemask, 64, '_');
setmem(findmask, 70, '_');
setmem(findstr, 70, ' ');
establish_window(1,2,80,24,TEXTFG,TEXTBG,TRUE);
editfunc = editkeys;
status_line = statusline;
mb = display_menubar(emn);
statusline();
if ((bf = malloc(BUFLEN)) != NULL) {
setmem(bf, BUFLEN, ' ');
strcpy(filename, file);
filename[strlen(filename)] = ' ';
if (*file)
read_file(" Loading ... ",bf,0,FALSE,FALSE);
while (TRUE) {
text_editor(bf, MAXLINES, EDITWIDTH);
if (bufferok("quit"))
break;
}
free(bf);
}
restore_menubar(mb);
delete_window();
}
/* ---------- load a file --------------- */
static int load_file(hs,vs)
{
if (bufferok("reload"))
strcpy(savefn, filename);
if (get_filename(" Load what file? ", TRUE) != ESC) {
setmem(ev.topptr, BUFLEN, ' ');
read_file(" Loading ... ",ev.topptr,0,FALSE,TRUE);
forcechar = BEGIN_BUFFER;
ev.text_changed = FALSE;
}
else
strcpy(filename, savefn);
return TRUE;
}
/* ---------- merge a file into the edit buffer -------- */
static int merge_file(hs,vs)
{
strcpy(savefn, filename);
if (get_filename(" Merge what file? ", TRUE) != ESC) {
if (read_file(" Merging ... ",
curr(0, ev.curr_y),
lineno(ev.curr_y), TRUE, TRUE)) {
forcechar = REPAINT;
ev.text_changed = TRUE;
}
}
strcpy(filename, savefn);
return TRUE;
}
/* --------- save the file -------------- */
static int save_file(hs,vs)
{
if (get_filename(" Save as what file? ", FALSE) != ESC)
if (write_file())
ev.text_changed = FALSE;
return TRUE;
}
/* ---------- start a new file ------------- */
static int new_file(hs,vs)
{
if (bufferok("erase"))
if (get_filename(" Build as what file? ",TRUE)!=ESC){
setmem(ev.topptr, BUFLEN, ' ');
forcechar = BEGIN_BUFFER;
ev.text_changed = FALSE;
}
return TRUE;
}
/* -------- read a file name ------------- */
static int get_filename(char *ttl, int clear)
{
int rtn;
establish_window(1,23,80,25,ENTRYFG,ENTRYBG,TRUE);
window_title(ttl);
gotoxy(3,2);
cputs("File name:");
rtn = data_entry(fn_template, clear, 1);
delete_window();
return rtn;
}
/* --------- write a file ------------ */
static int write_file()
{
FILE *fp;
int ln, i, ln1;
char *cp, buf[EDITWIDTH+1];
if ((fp = fopen(filename, "w")) == NULL) {
error_message(" Can't write that file! ");
return FALSE;
}
notice(" Writing file ... ");
/* ----- find the last significant line ----- */
for (ln = MAXLINES-1; ln > -1; --ln) {
cp = ev.topptr + ln * EDITWIDTH;
for (i = 0; i < EDITWIDTH; i++)
if (*(cp + i) != ' ')
break;
if (i < EDITWIDTH)
break;
}
for (ln1 = 0; ln1 <= ln; ln1++) {
movmem(ev.topptr + ln1 * EDITWIDTH, buf, EDITWIDTH);
i = EDITWIDTH-1;
cp = buf;
while (i >= 0 && *(cp + i) == ' ')
--i;
if (i == -1 || *(cp + i) != ' ')
i++;
*(cp + i) = '\n';
*(cp + i + 1) = '\0';
fputs(cp, fp);
}
fclose(fp);
delete_window();
return TRUE;
}
/* -------------- read (load or merge) a file ----------- */
static int
read_file(char *nt,char *ln,int lines,int merging,int needed)
{
FILE *fp;
char ibf[120];
char *cp;
int x;
if ((fp = fopen(filename, "r")) != NULL) {
notice(nt);
while (fgets(ibf, 120, fp) && lines < MAXLINES) {
lines++;
if (merging) {
movmem(ln,ln+EDITWIDTH,
BUFLEN-lines*EDITWIDTH);
setmem(ln,EDITWIDTH,' ');
}
cp = ibf, x = 0;
while (*cp && *cp != '\n') {
if (*cp == '\t')
x += TAB-(x%TAB);
else
*(ln+x++) = *cp;
cp++;
}
ln += EDITWIDTH;
}
fclose(fp);
delete_window();
return TRUE;
}
else if (needed)
error_message("No such file can be found");
return FALSE;
}
/* ----------- display a status line ----------- */
static void statusline()
{
char stat[81], *st;
int cl[81], *cp;
static char msk[] =
"Line:%3d Column:%2d %-9.9s %-21.21s F1:Help \
F10:Menu ";
unsigned y = 1;
unsigned x = 1;
unsigned attr = ((MENUFG | (MENUBG << 4)) << 8);
if (ev.wwd) {
y = (unsigned) (ev.nowptr-ev.topptr) / ev.wwd + 1;
x = (unsigned) (ev.nowptr-ev.topptr) % ev.wwd + 1;
}
sprintf(stat,msk,y,x,
(ev.edinsert ? "Insert" : "Overwrite"),
(ev.reforming ? "Auto Paragraph Reform" : " "));
for (st = stat, cp = cl; *st; st++)
*cp++ = (*st & 255) | attr;
__vram(__vptr(1,25),cl,80);
set_help("editor");
}
/* -------- get a string to find --------- */
static int findstring()
{
char *cp = findstr+60;
int ans;
establish_window(1,23,80,25,ENTRYFG,ENTRYBG,TRUE);
gotoxy(2,2);
cputs("Find?");
ans = data_entry(find_template, TRUE, 1);
delete_window();
if (ans == ESC)
return FALSE;
while (*--cp == ' ')
;
if (*cp)
*(cp+1) = '\0';
return TRUE;
}
/* -------- find a string in the buffer -------------- */
static char *find(char *bf, unsigned len)
{
char *cp;
for (cp = bf; cp < bf+len-strlen(findstr); cp++)
if (strncmp(cp, findstr, strlen(findstr)) == 0)
return cp;
return NULL;
}
/* ---------- test for buffer changed ----------- */
static int bufferok(char *s)
{
int c = 'Y';
if (ev.text_changed) {
establish_window(23,11,56,13,ERRORFG,ERRORBG,TRUE);
gotoxy(2,2);
cprintf("Text has changed, %s? (y/n)", s);
hidecursor();
do
putch(BELL), c = getkey();
while (toupper(c) != 'Y' && toupper(c) != 'N');
delete_window();
}
return toupper(c) == 'Y';
}
/* -------- small message ------------ */
static void notice(char *s)
{
int lf = (80-strlen(s))/2-1;
int rt = lf+strlen(s)+2;
establish_window(lf,11,rt,13,HELPFG,HELPBG,TRUE);
gotoxy(2,2);
cputs(s);
}
[LISTING 5]
/* ----------- twrp.c ------------ */
#include <conio.h>
#include "window.h"
#include "editor.h"
#include "help.h"
void main(int, char **);
void fileedit(char *);
void main(int argc, char **argv)
{
extern int inserting, MAXLINES;
MAXLINES = 800;
load_help("twrp.hlp");
clear_screen();
fileedit(argc > 1 ? argv[1] : "");
clear_screen();
inserting = FALSE;
insert_line();
}
[LISTING 6]
trwp (window.h, editor.h, help.h)
editshel (editor.h, menu.h, entry.h, help.h, window.h)
editor (editor.h, window.h)
entry (entry.h, window.h)
menu (menu.h, window.h)
help (help.h, window.h)
window (window.h)