📄 main.c
字号:
/*
* This file is part of the M-Edit program (Copyright 1996 by Vincenzo Morello)
* Permission to use is hereby granted for any purpose.
*
* Contains file handling and utility callbacks.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#if defined __TURBOC__ || defined _MSC_VER || defined __WATCOMC__
#include <io.h>
#ifndef R_OK
#define R_OK 04
#endif
#else
#include <unistd.h>
#endif
#ifdef MBCS_SUPPORT
#include <mbcsmgui.h>
#endif
#include "mgui.h"
#include "medit.h"
#include "me.h"
void LoadPrefs(void);
void SetWindowOptions(MOBJECT shell);
/*
* This array holds open windows OBJECT id
*/
MOBJECT windows[MAX_N_WINDOW];
#ifdef __WATCOMC__
void
mktemp(char *fname)
{
}
#endif
/*
* Free an undo item
*/
static void
FreeUndo(UNDO_DATA * pud)
{
if (pud->oldtext)
free(pud->oldtext);
if (pud->newtext)
free(pud->newtext);
free(pud);
}
/*
* Free all queued undo items for a window
*/
static void
FreeUndoList(FILE_DATA * pfd)
{
UNDO_DATA *pud, *tmp;
pud = pfd->first_undo;
while (pud)
{
tmp = pud;
pud = pud->next;
FreeUndo(tmp);
}
pfd->first_undo = NULL;
pfd->curr_undo = NULL;
pfd->undo_level = 0;
}
/*
* Read a file and ruturn the stream pointer and read-only status
*/
static char *
LoadFile(char *filename, int *ro)
{
FILE *fp;
char str[256];
char *buff;
struct stat sb;
int nread;
if (stat(filename, &sb) == -1)
{
sprintf(str, "Error accessing file:\n%s", filename);
MMessageDialog("Error", str, " Ok ", NULL);
return NULL;
}
if (sb.st_size > INT_MAX)
{
MMessageDialog("Sorry", "File is too large !", " Ok ", NULL);
return NULL;
}
if ((fp = fopen(filename, "r+")) == NULL)
{
if ((fp = fopen(filename, "r")) == NULL)
{
sprintf(str, "Failed to open file:\n%s", filename);
MMessageDialog("Error", str, " Ok ", NULL);
return NULL;
}
*ro = True;
}
else
{
*ro = False;
}
if ((buff = malloc((int) sb.st_size + 1)) == NULL)
{
MMessageDialog("ERROR", "Not Enough Memory,\nSorry", " Ok ", NULL);
}
else
{
nread = fread(buff, 1, (int) sb.st_size, fp);
buff[nread] = '\0';
}
fclose(fp);
return buff;
}
/*
* This callback handles cursor position change showing
*/
void
CursorPosCB(MOBJECT p, EDIT_CURS * pc, void *ad)
{
FILE_DATA *pfd;
MOBJECT shell;
char buff[64];
shell = MObjectShell(p);
pfd = (FILE_DATA *) MObjectGetUserData(shell);
if (pfd == NULL)
return;
sprintf(buff, "%4d", pc->pos_x + 1);
MObjectSetText(pfd->curs_x_label, buff);
sprintf(buff, "%4d", pc->pos_y + 1);
MObjectSetText(pfd->curs_y_label, buff);
}
void
AddUndoData(FILE_DATA * pfd,
char *oldtext, int start, int oldlen,
char *newtext, int newlen)
{
UNDO_DATA *pud, *tmp;
if (pfd->curr_undo || pfd->first_undo)
{
/*
* Cut any Undo-ed data (it cannot be Redo-ed)
*/
if (pfd->curr_undo)
{
pud = pfd->curr_undo->next;
pfd->curr_undo->next = NULL;
}
else
{
pud = pfd->first_undo;
pfd->first_undo = NULL;
}
while (pud)
{
tmp = pud;
pud = pud->next;
FreeUndo(tmp);
pfd->undo_level--;
}
}
if (pfd->undo_level == UNDO_DEPTH)
{
/*
* Cut the oldest undo data when maximum depth is reached
*/
tmp = pfd->first_undo;
pfd->first_undo = pfd->first_undo->next;
if (pfd->first_undo)
pfd->first_undo->prev = NULL;
FreeUndo(tmp);
pfd->undo_level--;
}
pud = (UNDO_DATA *) calloc(1, sizeof(UNDO_DATA));
if (pud == NULL)
{
if (oldtext)
free(oldtext);
if (newtext)
free(newtext);
return;
}
pud->start = start;
pud->oldlen = oldlen;
pud->newlen = newlen;
pud->oldtext = oldtext;
pud->newtext = newtext;
if (pfd->curr_undo)
pfd->curr_undo->next = pud;
pud->prev = pfd->curr_undo;
pfd->curr_undo = pud;
if (pfd->first_undo == NULL)
pfd->first_undo = pud;
pfd->undo_level++;
}
/*
* This callback handles the 'modified' status and queues undo items
*/
void
TextChangedCB(MOBJECT p, EDIT_CHANGE * ped, void *ad)
{
FILE_DATA *pfd;
MOBJECT shell;
char *oldtext = NULL;
char *newtext = NULL;
shell = MObjectShell(p);
pfd = MObjectGetUserData(shell);
if (!pfd->modified)
{
/*
* Set file modified status to True
*/
MObjectSetText(pfd->modified_label, "*");
pfd->modified = True;
}
if (ped->len > 0 && (oldtext = malloc(ped->len + 1)) == NULL)
{
return;
}
if (ped->change_len > 0 && (newtext = malloc(ped->change_len + 1)) == NULL)
{
if (oldtext)
free(oldtext);
return;
}
if (ped->len > 0)
{
strncpy(oldtext, ped->current_text + ped->pos, ped->len);
oldtext[ped->len] = '\0';
}
if (ped->change_len > 0)
{
strncpy(newtext, ped->change, ped->change_len);
newtext[ped->change_len] = '\0';
}
AddUndoData(pfd, oldtext, ped->pos, ped->len, newtext, ped->change_len);
}
/*
* This callback handles user's undo requests
*/
void
UndoCB(MOBJECT p, void *od, void *ad)
{
FILE_DATA *pfd;
UNDO_DATA *pud;
MOBJECT shell;
shell = MObjectShell(ad);
pfd = MObjectGetUserData(shell);
pud = pfd->curr_undo;
if (pud == NULL)
{
MBeep();
return;
}
MEditChangeText(pfd->edit,
pud->start, pud->newlen,
(pud->oldtext ? pud->oldtext : ""),
pud->oldlen);
pfd->curr_undo = pud->prev;
if (!pfd->modified)
{
/*
* Set file modified status to True
*/
MObjectSetText(pfd->modified_label, "*");
pfd->modified = True;
}
}
/*
* This callback handles user's redo requests
*/
void
RedoCB(MOBJECT p, void *od, void *ad)
{
FILE_DATA *pfd;
UNDO_DATA *pud;
MOBJECT shell;
shell = MObjectShell(ad);
pfd = MObjectGetUserData(shell);
pud = (pfd->curr_undo ? pfd->curr_undo->next : pfd->first_undo);
if (pud == NULL)
{
MBeep();
return;
}
MEditChangeText(pfd->edit,
pud->start, pud->oldlen,
(pud->newtext ? pud->newtext : ""),
pud->newlen);
pfd->curr_undo = pud;
if (!pfd->modified)
{
/*
* Set file modified status to True
*/
MObjectSetText(pfd->modified_label, "*");
pfd->modified = True;
}
}
/*
* This callback handles user's save-as request
*/
void
SaveAsCB(MOBJECT p, void *od, void *ad)
{
char pname[MAXPATHLEN];
char fname[MAXFNAMELEN];
MOBJECT shell = (MOBJECT) ad;
FILE_DATA *pfd = (FILE_DATA *) MObjectGetUserData(shell);
FILE *fp;
char str[256];
char *buff;
size_t len;
strcpy(fname, pfd->filename);
pname[0] = '\0';
if (!MFileSelection("Save File As ...", EXT, fname, pname, True))
return;
strcat(pname, fname);
if ((fp = fopen(pname, "w")) == NULL)
{
sprintf(str, "Cannot open file:\n%s\nfor writing!", pname);
MMessageDialog("Warning", str, " Ok ", NULL);
return;
}
buff = MObjectGetText(pfd->edit, NULL);
if (buff)
{
len = strlen(buff);
if (fwrite(buff, 1, len, fp) != len)
MMessageDialog("Error", "Write failed !!!", "Ok", NULL);
free(buff);
}
fclose(fp);
pfd->modified = False;
MObjectSetText(pfd->modified_label, " ");
if (pfd->read_only)
{
pfd->read_only = False;
MObjectSetSensitive(pfd->edit);
}
strcpy(pfd->pathname, pname);
strcpy(pfd->filename, fname);
MObjectSetText(pfd->fname_label, pfd->pathname);
MObjectSetText(shell, pfd->filename);
}
/*
* This callback handles user's save request
*/
void
SaveCB(MOBJECT p, void *od, void *ad)
{
MOBJECT shell = (MOBJECT) ad;
FILE_DATA *pfd = (FILE_DATA *) MObjectGetUserData(shell);
FILE *fp;
char str[256];
char *buff;
size_t len;
if (pfd->pathname[0] == '\0')
{
if (pfd->modified)
SaveAsCB(p, od, ad);
else
MMessageDialog("Warning", "No file open !", " Ok ", NULL);
return;
}
if (pfd->read_only)
{
sprintf(str, "File: %s\nis read only!", pfd->pathname);
MMessageDialog("Warning", str, " Ok ", NULL);
return;
}
if (!pfd->modified)
{
sprintf(str, "File:\n%s\nhas not been modified.\nSave anyway ?", pfd->pathname);
if (MMessageDialog("Warning", str, " Yes ", " Abort", NULL) != 0)
return;
}
if ((fp = fopen(pfd->pathname, "w")) == NULL)
{
sprintf(str, "Cannot open file:\n%s\nfor writing!", pfd->pathname);
MMessageDialog("Warning", str, " Ok ", NULL);
return;
}
buff = MObjectGetText(pfd->edit, NULL);
if (buff)
{
len = strlen(buff);
if (fwrite(buff, 1, len, fp) != len)
MMessageDialog("Error", "Write failed !!!", "Ok", NULL);
free(buff);
}
fclose(fp);
pfd->modified = False;
MObjectSetText(pfd->modified_label, " ");
/* FreeUndoList(pfd);
*/
}
/*
* This callback handles user's request to reload the file from disk
*/
void
RevertCB(MOBJECT p, void *od, void *ad)
{
MOBJECT shell = (MOBJECT) ad;
FILE_DATA *pfd = (FILE_DATA *) MObjectGetUserData(shell);
char str[256];
char *buff;
if (pfd->pathname[0] == '\0')
{
MMessageDialog("Warning", "No file open !", " Ok ", NULL);
return;
}
sprintf(str, "Are you sure you want to reload:\n\n%s ?\n", pfd->pathname);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -