⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 使用mgui写的类似xwindow下的编辑器程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -