[comp.sys.amiga] mg1b diff: sorted browser menu

jw@sics.se (Johan Widen) (09/12/87)

Enclosed is a diff for mg1b (MicroGNUEmacs) distributed on Fish disk 68.
mg has a directory browser that displays a directory in a menu. The directory
is unsorted. This makes it unnecessary hard to locate a file. The enclosed
diff adds code that sorts the names displayed in the browser menu.

I have only tried this under the Lattice compiler. There should only be one
problem with getting this to work under MANX: I used the Lattice library
routine tqsort to sort the names. This routine may not be available under
MANX. The declaration for tqsort is
	int tqsort(ta, n);
where ta is an array of string pointers (char *) and n is the number of
elements in the array. tqsort will sort ta using the procedure strcmp
to determine the order of the strings.

Sorry about this but I don't know what routines are available under MANX.

Now on to something different: string search and query replace in mg.
I usually prefer these to be case sensitive (and for query replace
not to do any strange things with Capital letters). I realize that some
people prefer string search to be case insensitive and that requirements
differ depending on what kind of text you are editing. It would be nice
if one could control the case sensitivity through a variable as you can in
GNU emacs. NOTE: I have not enclosed any diffs for this, it's just wishful
thinking.

: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
echo 'Extracting mg1b.diff'
sed 's/^X//' > mg1b.diff << '+ END-OF-FILE mg1b.diff'
X*** ../ttymenu.c	Sat Sep 12 01:27:08 1987
X--- ttymenu.c	Sat Sep 12 01:21:43 1987
X***************
X*** 24,29 ****
X--- 24,31 ----
X  extern struct Menu		*AutoMenu ;
X  extern struct Window		*EmW ;
X  
X+ extern char *malloc();
X+ 
X  #ifdef	LATTICE
X  static VOID	Add_Devices(ULONG) ;
X  #else
X***************
X*** 375,384 ****
X--- 377,406 ----
X  		return (readin(File_Name));		/* Read it in.	*/
X  	return TRUE;
X  	}
X+ 
X+ struct name_node {
X+ 	char *name;
X+ 	struct name_node *next;
X+ };
X+ 
X+ static void free_name_list(name_list)
X+ register struct name_node *name_list;
X+ {
X+ 	register struct name_node *tmp;
X+ 
X+ 	while(name_list) {
X+ 		tmp = name_list;
X+ 		name_list = name_list->next;
X+ 		free(tmp->name);
X+ 		free(tmp);
X+ 	}
X+ }
X+ 
X  /*
X   * Add_Dir - given a dir and a name, add the menu name with the files in
X   *	dir as entries.  Use AllocMem() in order to make
X   *      sure the file info block is on a longword boundary.
X+  *	The entries are sorted before they are added to the menu.
X   */
X  static
X  Add_Dir(dir, name) char *dir, *name; {
X***************
X*** 389,394 ****
X--- 411,419 ----
X  	static char			Name_Buf[LONGEST_NAME] ;
X  	char				*AllocMem();
X  	struct	FileInfoBlock		*File_Info;
X+ 	struct name_node		*name_list, *tmp_name;
X+ 	char				*cp, **name_table;
X+ 	int				i;
X  
X  	if ((File_Info = (struct FileInfoBlock *)
X  		AllocMem((LONG)sizeof(struct FileInfoBlock), 0L)) == NULL)
X***************
X*** 406,428 ****
X  		goto out;
X  
X  	if (Menu_Add(name, TRUE) == 0) goto out;
X  	for (count = 0; ExNext(my_lock, File_Info) 
X! 			|| IoErr() != ERROR_NO_MORE_ENTRIES; count++)
X! 		if (File_Info -> fib_DirEntryType < 0L) {
X! 			if (Menu_Item_Add(File_Info -> fib_FileName,
X  				(USHORT)ITEMENABLED, 0L, (BYTE)0)
X  					== MNUM(NOMENU, NOITEM, NOSUB))
X  					break ;
X! 			}
X! 		else {
X! 			(void) strcpy(Name_Buf, File_Info -> fib_FileName) ;
X! 			(void) strcat(Name_Buf, "/") ;
X! 			if (Menu_Item_Add(Name_Buf,
X! 				(USHORT) ITEMENABLED, 0L, (BYTE)0)
X! 					 == MNUM(NOMENU, NOITEM, NOSUB))
X! 				break ;
X! 			}
X! 	if (count == 0) Menu_Item_Add("EMPTY", (USHORT)0, 0L, (BYTE)0) ;
X  
X  	/* Put everything back */
X  	if (*last_char == '\0') *last_char = '/' ;
X--- 431,477 ----
X  		goto out;
X  
X  	if (Menu_Add(name, TRUE) == 0) goto out;
X+         name_list = NULL;
X  	for (count = 0; ExNext(my_lock, File_Info) 
X! 			|| IoErr() != ERROR_NO_MORE_ENTRIES; count++) {
X! 		(void) strcpy(Name_Buf, File_Info -> fib_FileName) ;
X! 		if (File_Info -> fib_DirEntryType >= 0L)
X! 			(void) strcat(Name_Buf, "/") ;
X! 		if(!(cp = malloc(strlen(Name_Buf) + 1))) {
X! 			free_name_list(name_list);
X! 			return(FALSE);
X! 		}
X! 		strcpy(cp, Name_Buf);
X! 		if(!(tmp_name = (struct name_node *)
X! 			malloc(sizeof(struct name_node)))) {
X! 			free_name_list(name_list);
X! 			return(FALSE);
X! 		}
X! 		tmp_name->name = cp;
X! 		tmp_name->next = name_list;
X! 		name_list = tmp_name;
X! 	}
X! 	if (count > 0) {
X! 		if (!(name_table = (char **) malloc(count*sizeof(char *)))) {
X! 			free_name_list(name_list);
X! 			return(FALSE);
X! 		}
X! 		i = count;
X! 		for (tmp_name = name_list; tmp_name;
X! 		     tmp_name = tmp_name->next) {
X! 			name_table[--i] = tmp_name->name;
X! 		}
X! 		tqsort(name_table, count);
X! 		for (i = 0; i < count; i++) {
X! 			if (Menu_Item_Add(name_table[i],
X  				(USHORT)ITEMENABLED, 0L, (BYTE)0)
X  					== MNUM(NOMENU, NOITEM, NOSUB))
X  					break ;
X! 		}
X! 		free_name_list(name_list);
X! 		free(name_table);
X! 	} else
X! 		 Menu_Item_Add("EMPTY", (USHORT)0, 0L, (BYTE)0) ;
X  
X  	/* Put everything back */
X  	if (*last_char == '\0') *last_char = '/' ;
X***************
X*** 452,457 ****
X--- 501,509 ----
X  	struct DosInfo			*dosinfo;
X  	UBYTE				buffer[80];
X  	int				ramflag = 0;
X+ 	struct name_node		*name_list, *tmp_name;
X+ 	char				*cp, **name_table;
X+ 	int				count, i;
X  
X  	/* if you've gotten this far, none of these will be null. */
X  	DosBase = (struct DosLibrary *) OpenLibrary(DOSNAME,0L);
X***************
X*** 461,466 ****
X--- 513,520 ----
X  	dosinfo = (struct DosInfo *) BADDR(rootnode->rn_Info);
X  	devlist = (struct DeviceList *) BADDR(dosinfo->di_DevInfo);
X  
X+         name_list = NULL;
X+ 	count = 0;
X  	while (devlist) {
X  		/* select by specified device type */
X  		if (devlist->dl_Type != devtype) {
X***************
X*** 476,495 ****
X  		 * disks should be the only devices added to the list. Magic
X  		 * disk test courtesy of Phillip Lindsay, Commodore-Amiga Inc.
X  		 */
X! 		if (devtype != DLT_DEVICE)
X! 			Menu_Item_Add(buffer,(USHORT)ITEMENABLED, 0L, (BYTE)0);
X! 		else if (devlist->dl_Task) {	/* why does this work? */
X! 			Menu_Item_Add(buffer,
X! 				(USHORT)ITEMENABLED, 0L, (BYTE)0);
X! 			if (!strcmp(buffer,"RAM:")) ramflag = 1;
X  		}
X  		devlist = (struct DeviceList *) BADDR(devlist->dl_Next);
X  	}
X- 	/* if ramdisk isn't loaded yet, add it anyway */
X- 	if ((devtype == DLT_DEVICE) && !ramflag)
X- 		Menu_Item_Add("RAM:",(USHORT)ITEMENABLED, 0L, (BYTE) 0);
X  	Permit();
X  	CloseLibrary(DosBase);
X  }
X  
X  btocstr(bp,buf,bufsiz)
X--- 530,586 ----
X  		 * disks should be the only devices added to the list. Magic
X  		 * disk test courtesy of Phillip Lindsay, Commodore-Amiga Inc.
X  		 */
X! 		if (devtype != DLT_DEVICE || devlist->dl_Task) {
X! 			count++;
X! 			if(!(cp = malloc(strlen(buffer) + 1))) {
X! 				free_name_list(name_list);
X! 				Permit();
X! 				CloseLibrary(DosBase);
X! 				return;
X! 			}
X! 			strcpy(cp, buffer);
X! 			if(!(tmp_name = (struct name_node *)
X! 				malloc(sizeof(struct name_node)))) {
X! 				free_name_list(name_list);
X! 				Permit();
X! 				CloseLibrary(DosBase);
X! 				return;
X! 			}
X! 			tmp_name->name = cp;
X! 			tmp_name->next = name_list;
X! 			name_list = tmp_name;
X! 			if (devtype == DLT_DEVICE &&
X! 			    !strcmp(buffer,"RAM:"))
X! 				ramflag = 1;
X  		}
X  		devlist = (struct DeviceList *) BADDR(devlist->dl_Next);
X  	}
X  	Permit();
X  	CloseLibrary(DosBase);
X+ 	if (count > 0 || (devtype == DLT_DEVICE && !ramflag)) {
X+ 		if (!(name_table = (char **)
X+ 			malloc((count + 1)*sizeof(char *)))) {
X+ 			free_name_list(name_list);
X+ 			return;
X+ 		}
X+ 		name_table[count] = "RAM:";
X+ 		i = count;
X+ 		for (tmp_name = name_list; tmp_name;
X+ 		     tmp_name = tmp_name->next) {
X+ 			name_table[--i] = tmp_name->name;
X+ 		}
X+ 		if(devtype == DLT_DEVICE && !ramflag)
X+ 			count++;
X+ 		tqsort(name_table, count);
X+ 		for (i = 0; i < count; i++) {
X+ 			if (Menu_Item_Add(name_table[i],
X+ 				(USHORT)ITEMENABLED, 0L, (BYTE)0)
X+ 					== MNUM(NOMENU, NOITEM, NOSUB))
X+ 					break ;
X+ 		}
X+ 		free_name_list(name_list);
X+ 		free(name_table);
X+ 	}
X  }
X  
X  btocstr(bp,buf,bufsiz)
+ END-OF-FILE mg1b.diff
chmod 'u=rw,g=rw,o=r' 'mg1b.diff'
echo '	-rw-rw-r--  1 jw           6523 Sep 12 18:28 mg1b.diff        (as sent)'
echo -n '	'
/bin/ls -l mg1b.diff
exit 0
-- 
Johan Widen
SICS, PO Box 1263, S-163 13 SPANGA, SWEDEN
{mcvax,munnari,cernvax,diku,inria,prlb2,penet,ukc,unido}!enea!sics.se!jw
Internet: jw@sics.se