home *** CD-ROM | disk | FTP | other *** search
/ Bila Vrana / BILA_VRANA.iso / 028A / MEDIT151.ZIP / MGUI / MEDIT / MAIN.C < prev    next >
C/C++ Source or Header  |  1996-09-07  |  20KB  |  790 lines

  1. /*
  2.  * This file is part of the M-Edit program (Copyright 1996 by Vincenzo Morello)
  3.  * Permission to use is hereby granted for any purpose.
  4.  *
  5.  * Contains file handling and utility callbacks.
  6.  */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <limits.h>
  11.  
  12. #if defined __TURBOC__ || defined _MSC_VER
  13. #include <io.h>
  14. #define R_OK    04
  15. #else
  16. #include <unistd.h>
  17. #endif
  18.  
  19. #include "mgui.h"
  20. #include "medit.h"
  21. #include "me.h"
  22.  
  23. void LoadPrefs(void);
  24. void SetWindowOptions(MOBJECT shell);
  25.  
  26. /*
  27.  * This array holds open windows OBJECT id
  28.  */
  29. MOBJECT windows[MAX_N_WINDOW];
  30.  
  31. /*
  32.  * This string points to the pathname of the configuration file
  33.  */
  34. char pref_fname[MAXPATHLEN+1];
  35.  
  36. /*
  37.  * Free an undo item
  38.  */
  39. static void FreeUndo(UNDO_DATA *pud)
  40. {
  41.     if (pud->oldtext)
  42.         free(pud->oldtext);
  43.     if (pud->newtext)
  44.         free(pud->newtext);
  45.     free(pud);
  46. }
  47.  
  48. /*
  49.  * Free all queued undo items for a window
  50.  */
  51. static void FreeUndoList(FILE_DATA *pfd)
  52. {
  53.     UNDO_DATA       *pud, *tmp;
  54.  
  55.     pud = pfd->first_undo;
  56.     while (pud) {
  57.         tmp = pud;
  58.         pud = pud->next;
  59.         FreeUndo(tmp);
  60.     }
  61.     pfd->first_undo = NULL;
  62.     pfd->curr_undo = NULL;
  63.     pfd->undo_level = 0;
  64. }
  65.  
  66. /*
  67.  * Read a file and ruturn the stream pointer and read-only status
  68.  */
  69. static char *LoadFile(char *filename, int *ro)
  70. {
  71.     FILE            *fp;
  72.     char            str[256];
  73.     char            *buff;
  74.     struct stat     sb;
  75.     int             nread;
  76.  
  77.     if (stat(filename, &sb) == -1) {
  78.         sprintf(str, "Error accessing file:\n%s", filename);
  79.         MMessageDialog("Error", str, " Ok ", NULL);
  80.         return NULL;
  81.     }
  82.     if (sb.st_size > (long)INT_MAX) {
  83.         MMessageDialog("Sorry", "File is too large !", " Ok ", NULL);
  84.         return NULL;
  85.     }
  86.     if ((fp=fopen(filename, "r+")) == NULL) {
  87.         if ((fp=fopen(filename, "r")) == NULL) {
  88.             sprintf(str, "Opening file:\n%s", filename);
  89.             MMessageDialog("Error", str, " Ok ", NULL);
  90.             return NULL;
  91.         }
  92.         *ro = True;
  93.     }
  94.     else {
  95.         *ro = False;
  96.     }
  97.     if ((buff = malloc((int)sb.st_size+1)) == NULL) {
  98.         MMessageDialog("ERROR", "Not Enough Memory,\nSorry", " Ok ", NULL);
  99.     }
  100.     else {
  101.         nread = fread(buff, 1, (int)sb.st_size, fp);
  102.         buff[nread] = '\0';
  103.     }
  104.     fclose(fp);
  105.     return buff;
  106. }
  107.  
  108.  
  109. /*
  110.  * This callback handles cursor position change showing
  111.  */
  112. void CursorPosCB(MOBJECT p, EDIT_CURS *pc, void *ad)
  113. {
  114.     FILE_DATA       *pfd;
  115.     MOBJECT         shell;
  116.     char            buff[64];
  117.  
  118.     shell = MObjectShell(p);
  119.     pfd = (FILE_DATA *)MObjectGetUserData(shell);
  120.     if (pfd == NULL)
  121.         return;
  122.     sprintf(buff, "%4d", pc->pos_x + 1);
  123.     MObjectSetText(pfd->curs_x_label, buff);
  124.     sprintf(buff, "%4d", pc->pos_y + 1);
  125.     MObjectSetText(pfd->curs_y_label, buff);
  126. }
  127.  
  128. void AddUndoData(FILE_DATA *pfd,
  129.     char *oldtext, int start, int oldlen,
  130.     char *newtext, int newlen)
  131. {
  132.     UNDO_DATA       *pud, *tmp;
  133.  
  134.     if (pfd->curr_undo || pfd->first_undo) {
  135. /*
  136.  * Cut any Undo-ed data (it cannot be Redo-ed)
  137.  */
  138.         if (pfd->curr_undo) {
  139.             pud = pfd->curr_undo->next;
  140.             pfd->curr_undo->next = NULL;
  141.         }
  142.         else {
  143.             pud = pfd->first_undo;
  144.             pfd->first_undo = NULL;
  145.         }
  146.         while (pud) {
  147.             tmp = pud;
  148.             pud = pud->next;
  149.             FreeUndo(tmp);
  150.             pfd->undo_level--;
  151.         }
  152.     }
  153.  
  154.     if (pfd->undo_level == UNDO_DEPTH) {
  155. /*
  156.  * Cut the oldest undo data when maximum depth is reached
  157.  */
  158.         tmp = pfd->first_undo;
  159.         pfd->first_undo = pfd->first_undo->next;
  160.         if (pfd->first_undo)
  161.             pfd->first_undo->prev = NULL;
  162.         FreeUndo(tmp);
  163.         pfd->undo_level--;
  164.     }
  165.  
  166.     pud = (UNDO_DATA *)calloc(1, sizeof(UNDO_DATA));
  167.     if (pud == NULL) {
  168.         if (oldtext)
  169.             free(oldtext);
  170.         if (newtext)
  171.             free(newtext);
  172.         return;
  173.     }
  174.  
  175.     pud->start = start;
  176.     pud->oldlen = oldlen;
  177.     pud->newlen = newlen;
  178.     pud->oldtext = oldtext;
  179.     pud->newtext = newtext;
  180.  
  181.     if (pfd->curr_undo)
  182.         pfd->curr_undo->next = pud;
  183.     pud->prev = pfd->curr_undo;
  184.     pfd->curr_undo = pud;
  185.     if (pfd->first_undo == NULL)
  186.         pfd->first_undo = pud;
  187.  
  188.     pfd->undo_level++;
  189. }
  190.  
  191. /*
  192.  * This callback handles the 'modified' status and queues undo items
  193.  */
  194. void TextChangedCB(MOBJECT p, EDIT_CHANGE *ped, void *ad)
  195. {
  196.     FILE_DATA       *pfd;
  197.     MOBJECT         shell;
  198.     char            *oldtext = NULL;
  199.     char            *newtext = NULL;
  200.  
  201.     shell = MObjectShell(p);
  202.     pfd = MObjectGetUserData(shell);
  203.  
  204.     if (!pfd->modified) {
  205. /*
  206.  * Set file modified status to True
  207.  */
  208.         MObjectSetText(pfd->modified_label, "*");
  209.         pfd->modified = True;
  210.     }
  211.     if (ped->len > 0 && (oldtext = malloc(ped->len+1)) == NULL) {
  212.         return;
  213.     }
  214.     if (ped->change_len > 0 && (newtext = malloc( ped->change_len+1)) == NULL) {
  215.         if (oldtext)
  216.             free(oldtext);
  217.         return;
  218.     }
  219.     if (ped->len > 0) {
  220.         strncpy(oldtext, ped->current_text+ped->pos, ped->len);
  221.         oldtext[ped->len] = '\0';
  222.     }
  223.     if (ped->change_len > 0) {
  224.         strncpy(newtext, ped->change, ped->change_len);
  225.         newtext[ped->change_len] = '\0';
  226.     }
  227.     AddUndoData(pfd, oldtext, ped->pos, ped->len, newtext, ped->change_len);
  228. }
  229.  
  230. /*
  231.  * This callback handles user's undo requests
  232.  */
  233. void UndoCB(MOBJECT p, void *od, void *ad)
  234. {
  235.     FILE_DATA       *pfd;
  236.     UNDO_DATA       *pud;
  237.     MOBJECT         shell;
  238.  
  239.     shell = MObjectShell(ad);
  240.     pfd = MObjectGetUserData(shell);
  241.     pud = pfd->curr_undo;
  242.     if (pud == NULL) {
  243.         MBeep();
  244.         return;
  245.     }
  246.     MEditChangeText(pfd->edit,
  247.         pud->start, pud->newlen,
  248.         (pud->oldtext ? pud->oldtext : ""),
  249.         pud->oldlen);
  250.     pfd->curr_undo = pud->prev;
  251.     if (!pfd->modified) {
  252. /*
  253.  * Set file modified status to True
  254.  */
  255.         MObjectSetText(pfd->modified_label, "*");
  256.         pfd->modified = True;
  257.     }
  258. }
  259.  
  260. /*
  261.  * This callback handles user's redo requests
  262.  */
  263. void RedoCB(MOBJECT p, void *od, void *ad)
  264. {
  265.     FILE_DATA       *pfd;
  266.     UNDO_DATA       *pud;
  267.     MOBJECT         shell;
  268.  
  269.     shell = MObjectShell(ad);
  270.     pfd = MObjectGetUserData(shell);
  271.     pud = (pfd->curr_undo ? pfd->curr_undo->next : pfd->first_undo);
  272.     if (pud == NULL) {
  273.         MBeep();
  274.         return;
  275.     }
  276.     MEditChangeText(pfd->edit,
  277.         pud->start, pud->oldlen,
  278.         (pud->newtext ? pud->newtext : ""),
  279.         pud->newlen);
  280.     pfd->curr_undo = pud;
  281.     if (!pfd->modified) {
  282. /*
  283.  * Set file modified status to True
  284.  */
  285.         MObjectSetText(pfd->modified_label, "*");
  286.         pfd->modified = True;
  287.     }
  288. }
  289.  
  290. /*
  291.  * This callback handles user's save request
  292.  */
  293. void SaveCB(MOBJECT p, void *od, void *ad)
  294. {
  295.     MOBJECT         shell = (MOBJECT)ad;
  296.     FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
  297.     FILE            *fp;
  298.     char    str[256];
  299.     char    *buff;
  300.     int        len;
  301.  
  302.     if (pfd->pathname[0] == '\0') {
  303.         if (pfd->modified) {
  304.             if (!MFileSelection("Save File As ...", EXT,
  305.                  pfd->filename, pfd->pathname, True))
  306.                 return;
  307.             strcat(pfd->pathname, pfd->filename);
  308.             MObjectSetText(pfd->fname_label, pfd->pathname);
  309.         }
  310.         else
  311.             MMessageDialog("Warning", "No file open !", " Ok ", NULL);
  312.         return;
  313.     }
  314.     if (pfd->read_only) {
  315.         sprintf(str, "File: %s\nis read only!", pfd->pathname);
  316.         MMessageDialog("Warning", str, " Ok ", NULL);
  317.         return;
  318.     }
  319.     if (!pfd->modified) {
  320.         sprintf(str, "File:\n%s\nhas not been modified.\nSave anyway ?", pfd->pathname);
  321.         if (MMessageDialog("Warning", str, " Yes ", " Abort", NULL) != 0)
  322.             return;
  323.     }
  324.     if ((fp = fopen(pfd->pathname, "w")) == NULL) {
  325.         sprintf(str, "Cannot open file:\n%s\nfor writing!", pfd->pathname);
  326.         MMessageDialog("Warning", str, " Ok ", NULL);
  327.         return;
  328.     }
  329.     buff = MObjectGetText(pfd->edit, NULL);
  330.     if (buff) {
  331.         len = strlen(buff);
  332.         if (fwrite(buff, 1, len, fp) != len)
  333.             MMessageDialog("Error", "Writing file", "Ok", NULL);
  334.         free(buff);
  335.     }
  336.     fclose(fp);
  337.     pfd->modified = False;
  338.     MObjectSetText(pfd->modified_label, " ");
  339. /*      FreeUndoList(pfd);
  340. */
  341. }
  342.  
  343. /*
  344.  * This callback handles user's save-as request
  345.  */
  346. void SaveAsCB(MOBJECT p, void *od, void *ad)
  347. {
  348.     char            pname[MAXPATHLEN];
  349.     MOBJECT         shell = (MOBJECT)ad;
  350.     FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
  351.  
  352.     if (!MFileSelection("Save File As ...", EXT, pfd->filename, pname, True))
  353.         return;
  354.     strcpy(pfd->pathname, pname);
  355.     strcat(pfd->pathname, pfd->filename);
  356.     MObjectSetText(pfd->fname_label, pfd->pathname);
  357.     MObjectSetText(shell, pfd->filename);
  358.     pfd->mod